~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Jay Pipes
  • Date: 2009-09-15 21:01:42 UTC
  • mto: (1126.2.5 merge)
  • mto: This revision was merged to the branch mainline in revision 1128.
  • Revision ID: jpipes@serialcoder-20090915210142-x8mwiqn1q0vzjspp
Moves Alter_info out into its own header and source file, cleans up some related include mess in sql_lex.h, and renames Alter_info to AlterInfo.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2009 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2009 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include "config.h"
22
 
 
23
 
#include <fcntl.h>
24
 
 
25
 
#include <sstream>
26
 
 
27
 
#include "drizzled/show.h"
28
 
#include "drizzled/lock.h"
29
 
#include "drizzled/session.h"
30
 
#include "drizzled/statement/alter_table.h"
31
 
#include "drizzled/global_charset_info.h"
32
 
 
 
21
#include <drizzled/server_includes.h>
 
22
#include <drizzled/show.h>
 
23
#include <drizzled/lock.h>
 
24
#include <drizzled/session.h>
 
25
#include <drizzled/statement/alter_table.h>
33
26
 
34
27
#include "drizzled/gettext.h"
35
28
#include "drizzled/data_home.h"
36
29
#include "drizzled/sql_table.h"
37
30
#include "drizzled/table_proto.h"
38
 
#include "drizzled/optimizer/range.h"
39
 
#include "drizzled/time_functions.h"
40
 
#include "drizzled/records.h"
41
 
#include "drizzled/pthread_globals.h"
42
 
#include "drizzled/internal/my_sys.h"
43
 
#include "drizzled/internal/iocache.h"
44
 
#include "drizzled/plugin/storage_engine.h"
45
 
#include <drizzled/copy_field.h>
46
 
 
47
 
#include "drizzled/transaction_services.h"
48
 
 
49
 
#include "drizzled/filesort.h"
50
 
 
51
 
#include "drizzled/message.h"
52
 
 
53
 
using namespace std;
54
 
 
55
 
namespace drizzled
56
 
{
57
 
 
58
 
extern pid_t current_pid;
59
 
 
60
 
static int copy_data_between_tables(Session *session,
61
 
                                    Table *from,Table *to,
 
31
 
 
32
using namespace drizzled;
 
33
 
 
34
static int copy_data_between_tables(Table *from,Table *to,
62
35
                                    List<CreateField> &create,
63
36
                                    bool ignore,
64
37
                                    uint32_t order_num,
65
 
                                    Order *order,
 
38
                                    order_st *order,
66
39
                                    ha_rows *copied,
67
40
                                    ha_rows *deleted,
68
41
                                    enum enum_enable_or_disable keys_onoff,
69
42
                                    bool error_if_not_empty);
70
 
 
71
 
static bool prepare_alter_table(Session *session,
 
43
static bool mysql_prepare_alter_table(Session *session,
72
44
                                      Table *table,
73
45
                                      HA_CREATE_INFO *create_info,
74
 
                                      const message::Table &original_proto,
75
 
                                      message::Table &table_message,
 
46
                                      message::Table *table_proto,
76
47
                                      AlterInfo *alter_info);
77
 
 
78
 
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
79
 
 
80
 
namespace statement {
81
 
 
82
 
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
83
 
  CreateTable(in_session)
84
 
85
 
  in_session->lex->sql_command= SQLCOM_ALTER_TABLE;
86
 
  (void)ident;
87
 
  alter_info.build_method= build_arg;
88
 
}
89
 
 
90
 
} // namespace statement
 
48
static int create_temporary_table(Session *session,
 
49
                                  Table *table,
 
50
                                  char *new_db,
 
51
                                  char *tmp_name,
 
52
                                  HA_CREATE_INFO *create_info,
 
53
                                  message::Table *create_proto,
 
54
                                  AlterInfo *alter_info);
91
55
 
92
56
bool statement::AlterTable::execute()
93
57
{
94
 
  TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
95
 
  TableList *all_tables= getSession()->lex->query_tables;
 
58
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
 
59
  TableList *all_tables= session->lex->query_tables;
96
60
  assert(first_table == all_tables && first_table != 0);
97
 
  Select_Lex *select_lex= &getSession()->lex->select_lex;
 
61
  Select_Lex *select_lex= &session->lex->select_lex;
98
62
  bool need_start_waiting= false;
99
63
 
100
 
  is_engine_set= not createTableMessage().engine().name().empty();
 
64
  /*
 
65
     Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
 
66
     so we have to use a copy of this structure to make execution
 
67
     prepared statement- safe. A shallow copy is enough as no memory
 
68
     referenced from this structure will be modified.
 
69
   */
 
70
  HA_CREATE_INFO create_info(session->lex->create_info);
 
71
  AlterInfo alter_info(session->lex->alter_info, session->mem_root);
101
72
 
102
 
  if (is_engine_set)
 
73
  if (session->is_fatal_error) /* out of memory creating a copy of alter_info */
103
74
  {
104
 
    create_info().db_type= 
105
 
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
106
 
 
107
 
    if (create_info().db_type == NULL)
108
 
    {
109
 
      my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
110
 
 
111
 
      return true;
112
 
    }
 
75
    return true;
113
76
  }
114
77
 
115
78
  /* Must be set in the parser */
116
79
  assert(select_lex->db);
117
80
 
118
 
  /* Chicken/Egg... we need to search for the table, to know if the table exists, so we can build a full identifier from it */
119
 
  message::table::shared_ptr original_table_message;
120
 
  {
121
 
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
 
    if (plugin::StorageEngine::getTableDefinition(*getSession(), identifier, original_table_message) != EEXIST)
123
 
    {
124
 
      my_error(ER_BAD_TABLE_ERROR, identifier);
125
 
      return true;
126
 
    }
127
 
 
128
 
    if (not  create_info().db_type)
129
 
    {
130
 
      create_info().db_type= 
131
 
        plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
132
 
 
133
 
      if (not create_info().db_type)
134
 
      {
135
 
        my_error(ER_BAD_TABLE_ERROR, identifier);
136
 
        return true;
137
 
      }
138
 
    }
139
 
  }
140
 
 
141
 
  if (not validateCreateTableOption())
142
 
    return true;
143
 
 
144
 
  if (getSession()->inTransaction())
145
 
  {
146
 
    my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
147
 
    return true;
148
 
  }
149
 
 
150
 
  if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
151
 
    return true;
152
 
 
153
 
  bool res;
154
 
  if (original_table_message->type() == message::Table::STANDARD )
155
 
  {
156
 
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
 
    identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
158
 
                                   getSession()->lex->name.str ? getSession()->lex->name.str : first_table->getTableName());
159
 
 
160
 
    res= alter_table(getSession(), 
161
 
                     identifier,
162
 
                     new_identifier,
163
 
                     &create_info(),
164
 
                     *original_table_message,
165
 
                     createTableMessage(),
166
 
                     first_table,
167
 
                     &alter_info,
168
 
                     select_lex->order_list.elements,
169
 
                     (Order *) select_lex->order_list.first,
170
 
                     getSession()->lex->ignore);
171
 
  }
172
 
  else
173
 
  {
174
 
    identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
 
    Table *table= getSession()->find_temporary_table(catch22);
176
 
    assert(table);
177
 
    {
178
 
      identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
 
      identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
180
 
                                       getSession()->lex->name.str ? getSession()->lex->name.str : first_table->getTableName(),
181
 
                                       table->getMutableShare()->getPath());
182
 
 
183
 
      res= alter_table(getSession(), 
184
 
                       identifier,
185
 
                       new_identifier,
186
 
                       &create_info(),
187
 
                       *original_table_message,
188
 
                       createTableMessage(),
189
 
                       first_table,
190
 
                       &alter_info,
191
 
                       select_lex->order_list.elements,
192
 
                       (Order *) select_lex->order_list.first,
193
 
                       getSession()->lex->ignore);
194
 
    }
195
 
  }
196
 
 
 
81
  /* ALTER TABLE ends previous transaction */
 
82
  if (! session->endActiveTransaction())
 
83
  {
 
84
    return true;
 
85
  }
 
86
 
 
87
  if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
88
  {
 
89
    return true;
 
90
  }
 
91
 
 
92
  bool res= mysql_alter_table(session, 
 
93
                              select_lex->db, 
 
94
                              session->lex->name.str,
 
95
                              &create_info,
 
96
                              session->lex->create_table_proto,
 
97
                              first_table,
 
98
                              &alter_info,
 
99
                              select_lex->order_list.elements,
 
100
                              (order_st *) select_lex->order_list.first,
 
101
                              session->lex->ignore);
197
102
  /*
198
103
     Release the protection against the global read lock and wake
199
104
     everyone, who might want to set a global read lock.
200
105
   */
201
 
  getSession()->startWaitingGlobalReadLock();
202
 
 
 
106
  start_waiting_global_read_lock(session);
203
107
  return res;
204
108
}
205
109
 
206
 
 
207
110
/**
208
111
  Prepare column and key definitions for CREATE TABLE in ALTER Table.
209
112
 
244
147
                 Table instructions
245
148
  @retval false  success
246
149
*/
247
 
static bool prepare_alter_table(Session *session,
248
 
                                Table *table,
249
 
                                HA_CREATE_INFO *create_info,
250
 
                                const message::Table &original_proto,
251
 
                                message::Table &table_message,
252
 
                                AlterInfo *alter_info)
 
150
static bool mysql_prepare_alter_table(Session *session,
 
151
                                      Table *table,
 
152
                                      HA_CREATE_INFO *create_info,
 
153
                                      message::Table *table_proto,
 
154
                                      AlterInfo *alter_info)
253
155
{
254
156
  /* New column definitions are added here */
255
157
  List<CreateField> new_create_list;
256
158
  /* New key definitions are added here */
257
159
  List<Key> new_key_list;
258
 
  List_iterator<AlterDrop> drop_it(alter_info->drop_list);
 
160
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
259
161
  List_iterator<CreateField> def_it(alter_info->create_list);
260
 
  List_iterator<AlterColumn> alter_it(alter_info->alter_list);
 
162
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
261
163
  List_iterator<Key> key_it(alter_info->key_list);
262
164
  List_iterator<CreateField> find_it(new_create_list);
263
165
  List_iterator<CreateField> field_it(new_create_list);
264
166
  List<Key_part_spec> key_parts;
265
167
  uint32_t used_fields= create_info->used_fields;
266
 
  KeyInfo *key_info= table->key_info;
 
168
  KEY *key_info=table->key_info;
267
169
  bool rc= true;
268
170
 
 
171
 
269
172
  /* Let new create options override the old ones */
270
173
  message::Table::TableOptions *table_options;
271
 
  table_options= table_message.mutable_options();
272
 
 
273
 
  if (not (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
274
 
    create_info->default_table_charset= table->getShare()->table_charset;
275
 
 
276
 
  if (not (used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
277
 
  {
 
174
  table_options= table_proto->mutable_options();
 
175
 
 
176
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
177
    create_info->block_size= table->s->block_size;
 
178
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
179
    create_info->default_table_charset= table->s->table_charset;
 
180
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
181
    {
278
182
    /* Table has an autoincrement, copy value to new table */
279
 
    table->cursor->info(HA_STATUS_AUTO);
280
 
    create_info->auto_increment_value= table->cursor->stats.auto_increment_value;
281
 
    if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
282
 
      table_options->set_has_user_set_auto_increment_value(false);
 
183
    table->file->info(HA_STATUS_AUTO);
 
184
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
283
185
  }
 
186
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
187
    create_info->key_block_size= table->s->key_block_size;
284
188
 
285
 
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
 
189
  table->restoreRecordAsDefault();     // Empty record for DEFAULT
286
190
  CreateField *def;
287
191
 
288
 
  /* First collect all fields from table which isn't in drop_list */
289
 
  Field *field;
290
 
  for (Field **f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
 
192
    /*
 
193
    First collect all fields from table which isn't in drop_list
 
194
    */
 
195
  Field **f_ptr,*field;
 
196
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
291
197
  {
292
198
    /* Check if field should be dropped */
293
 
    AlterDrop *drop;
 
199
    Alter_drop *drop;
294
200
    drop_it.rewind();
295
 
    while ((drop= drop_it++))
 
201
    while ((drop=drop_it++))
296
202
    {
297
 
      if (drop->type == AlterDrop::COLUMN &&
298
 
          ! my_strcasecmp(system_charset_info, field->field_name, drop->name))
 
203
      if (drop->type == Alter_drop::COLUMN &&
 
204
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
299
205
      {
300
 
        /* Reset auto_increment value if it was dropped */
301
 
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
302
 
            ! (used_fields & HA_CREATE_USED_AUTO))
303
 
        {
304
 
          create_info->auto_increment_value= 0;
305
 
          create_info->used_fields|= HA_CREATE_USED_AUTO;
306
 
        }
307
 
        break;
 
206
        /* Reset auto_increment value if it was dropped */
 
207
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
208
            !(used_fields & HA_CREATE_USED_AUTO))
 
209
        {
 
210
          create_info->auto_increment_value=0;
 
211
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
212
        }
 
213
        break;
308
214
      }
309
215
    }
310
 
 
311
216
    if (drop)
312
217
    {
313
218
      drop_it.remove();
319
224
 
320
225
    /* Check if field is changed */
321
226
    def_it.rewind();
322
 
    while ((def= def_it++))
 
227
    while ((def=def_it++))
323
228
    {
324
229
      if (def->change &&
325
 
          ! my_strcasecmp(system_charset_info, field->field_name, def->change))
326
 
              break;
 
230
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
231
        break;
327
232
    }
328
 
 
329
233
    if (def)
330
 
    {
331
 
      /* Field is changed */
332
 
      def->field= field;
333
 
      if (! def->after)
 
234
    {                                           // Field is changed
 
235
      def->field=field;
 
236
      if (!def->after)
334
237
      {
335
 
        new_create_list.push_back(def);
336
 
        def_it.remove();
 
238
        new_create_list.push_back(def);
 
239
        def_it.remove();
337
240
      }
338
241
    }
339
242
    else
344
247
      */
345
248
      def= new CreateField(field, field);
346
249
      new_create_list.push_back(def);
347
 
      alter_it.rewind(); /* Change default if ALTER */
348
 
      AlterColumn *alter;
349
 
 
350
 
      while ((alter= alter_it++))
 
250
      alter_it.rewind();                        // Change default if ALTER
 
251
      Alter_column *alter;
 
252
      while ((alter=alter_it++))
351
253
      {
352
 
        if (! my_strcasecmp(system_charset_info,field->field_name, alter->name))
353
 
          break;
 
254
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
255
          break;
354
256
      }
355
 
 
356
257
      if (alter)
357
258
      {
358
 
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
359
 
        {
360
 
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
361
 
          return true;
362
 
        }
363
 
 
364
 
        if ((def->def= alter->def))
365
 
        {
366
 
          /* Use new default */
 
259
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
 
260
        {
 
261
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
262
          goto err;
 
263
        }
 
264
        if ((def->def=alter->def))              // Use new default
367
265
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
368
 
        }
369
266
        else
370
 
        {
371
267
          def->flags|= NO_DEFAULT_VALUE_FLAG;
372
 
        }
373
 
        alter_it.remove();
 
268
        alter_it.remove();
374
269
      }
375
270
    }
376
271
  }
377
 
 
378
272
  def_it.rewind();
379
 
  while ((def= def_it++)) /* Add new columns */
 
273
  while ((def=def_it++))                        // Add new columns
380
274
  {
381
275
    if (def->change && ! def->field)
382
276
    {
383
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
384
 
      return true;
 
277
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
278
      goto err;
385
279
    }
386
280
    /*
387
 
      If we have been given a field which has no default value, and is not null then we need to bail.
 
281
      Check that the DATE/DATETIME not null field we are going to add is
 
282
      either has a default value or the '0000-00-00' is allowed by the
 
283
      set sql mode.
 
284
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
285
      flag to allow ALTER Table only if the table to be altered is empty.
388
286
    */
389
 
    if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
 
287
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
288
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
289
        !alter_info->datetime_field &&
 
290
        !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
291
        session->variables.sql_mode & MODE_NO_ZERO_DATE)
390
292
    {
 
293
      alter_info->datetime_field= def;
391
294
      alter_info->error_if_not_empty= true;
392
295
    }
393
 
    if (! def->after)
394
 
    {
 
296
    if (!def->after)
395
297
      new_create_list.push_back(def);
396
 
    }
397
298
    else if (def->after == first_keyword)
398
 
    {
399
299
      new_create_list.push_front(def);
400
 
    }
401
300
    else
402
301
    {
403
302
      CreateField *find;
404
303
      find_it.rewind();
405
 
 
406
 
      while ((find= find_it++)) /* Add new columns */
407
 
      {
408
 
        if (not my_strcasecmp(system_charset_info,def->after, find->field_name))
409
 
          break;
410
 
      }
411
 
 
412
 
      if (not find)
413
 
      {
414
 
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
415
 
        return true;
416
 
      }
417
 
 
418
 
      find_it.after(def); /* Put element after this */
419
 
 
 
304
      while ((find=find_it++))                  // Add new columns
 
305
      {
 
306
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
307
          break;
 
308
      }
 
309
      if (!find)
 
310
      {
 
311
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
312
        goto err;
 
313
      }
 
314
      find_it.after(def);                       // Put element after this
420
315
      /*
421
316
        XXX: hack for Bug#28427.
422
317
        If column order has changed, force OFFLINE ALTER Table
429
324
      */
430
325
      if (alter_info->build_method == HA_BUILD_ONLINE)
431
326
      {
432
 
        my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
433
 
        return true;
 
327
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
328
        goto err;
434
329
      }
435
 
 
436
330
      alter_info->build_method= HA_BUILD_OFFLINE;
437
331
    }
438
332
  }
439
 
 
440
333
  if (alter_info->alter_list.elements)
441
334
  {
442
 
    my_error(ER_BAD_FIELD_ERROR,
443
 
             MYF(0),
444
 
             alter_info->alter_list.head()->name,
445
 
             table->getMutableShare()->getTableName());
446
 
    return true;
 
335
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
336
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
337
    goto err;
447
338
  }
448
 
 
449
 
  if (not new_create_list.elements)
 
339
  if (!new_create_list.elements)
450
340
  {
451
 
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
 
               ER(ER_CANT_REMOVE_ALL_FIELDS),
 
341
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
453
342
               MYF(0));
454
 
    return true;
 
343
    goto err;
455
344
  }
456
345
 
457
346
  /*
458
347
    Collect all keys which isn't in drop list. Add only those
459
348
    for which some fields exists.
460
349
  */
461
 
  for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
 
350
 
 
351
  for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
462
352
  {
463
353
    char *key_name= key_info->name;
464
 
    AlterDrop *drop;
465
 
 
 
354
    Alter_drop *drop;
466
355
    drop_it.rewind();
467
 
    while ((drop= drop_it++))
 
356
    while ((drop=drop_it++))
468
357
    {
469
 
      if (drop->type == AlterDrop::KEY &&
470
 
          ! my_strcasecmp(system_charset_info, key_name, drop->name))
471
 
        break;
 
358
      if (drop->type == Alter_drop::KEY &&
 
359
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
360
        break;
472
361
    }
473
 
 
474
362
    if (drop)
475
363
    {
476
364
      drop_it.remove();
477
365
      continue;
478
366
    }
479
367
 
480
 
    KeyPartInfo *key_part= key_info->key_part;
 
368
    KEY_PART_INFO *key_part= key_info->key_part;
481
369
    key_parts.empty();
482
 
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
 
370
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
483
371
    {
484
 
      if (! key_part->field)
485
 
              continue; /* Wrong field (from UNIREG) */
486
 
 
487
 
      const char *key_part_name= key_part->field->field_name;
 
372
      if (!key_part->field)
 
373
        continue;                               // Wrong field (from UNIREG)
 
374
      const char *key_part_name=key_part->field->field_name;
488
375
      CreateField *cfield;
489
376
      field_it.rewind();
490
 
      while ((cfield= field_it++))
 
377
      while ((cfield=field_it++))
491
378
      {
492
 
        if (cfield->change)
493
 
        {
494
 
          if (not my_strcasecmp(system_charset_info, key_part_name, cfield->change))
495
 
            break;
496
 
        }
497
 
        else if (not my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
498
 
          break;
 
379
        if (cfield->change)
 
380
        {
 
381
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
382
                             cfield->change))
 
383
            break;
 
384
        }
 
385
        else if (!my_strcasecmp(system_charset_info,
 
386
                                key_part_name, cfield->field_name))
 
387
          break;
499
388
      }
500
 
 
501
 
      if (not cfield)
502
 
              continue; /* Field is removed */
503
 
      
504
 
      uint32_t key_part_length= key_part->length;
505
 
      if (cfield->field) /* Not new field */
 
389
      if (!cfield)
 
390
        continue;                               // Field is removed
 
391
      uint32_t key_part_length=key_part->length;
 
392
      if (cfield->field)                        // Not new field
506
393
      {
507
394
        /*
508
395
          If the field can't have only a part used in a key according to its
516
403
          BLOBs may have cfield->length == 0, which is why we test it before
517
404
          checking whether cfield->length < key_part_length (in chars).
518
405
         */
519
 
        if (! Field::type_can_have_key_part(cfield->field->type()) ||
520
 
            ! Field::type_can_have_key_part(cfield->sql_type) ||
521
 
            (cfield->field->field_length == key_part_length) ||
522
 
            (cfield->length &&
523
 
             (cfield->length < key_part_length / key_part->field->charset()->mbmaxlen)))
524
 
          key_part_length= 0; /* Use whole field */
 
406
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
407
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
408
            (cfield->field->field_length == key_part_length &&
 
409
             !f_is_blob(key_part->key_type)) ||
 
410
            (cfield->length && (cfield->length < key_part_length /
 
411
                                key_part->field->charset()->mbmaxlen)))
 
412
          key_part_length= 0;                   // Use whole field
525
413
      }
526
 
      key_part_length/= key_part->field->charset()->mbmaxlen;
 
414
      key_part_length /= key_part->field->charset()->mbmaxlen;
527
415
      key_parts.push_back(new Key_part_spec(cfield->field_name,
528
416
                                            strlen(cfield->field_name),
529
 
                                            key_part_length));
 
417
                                            key_part_length));
530
418
    }
531
419
    if (key_parts.elements)
532
420
    {
533
 
      key_create_information_st key_create_info= default_key_create_info;
 
421
      KEY_CREATE_INFO key_create_info;
534
422
      Key *key;
535
 
      Key::Keytype key_type;
 
423
      enum Key::Keytype key_type;
 
424
      memset(&key_create_info, 0, sizeof(key_create_info));
536
425
 
537
426
      key_create_info.algorithm= key_info->algorithm;
538
 
 
539
427
      if (key_info->flags & HA_USES_BLOCK_SIZE)
540
428
        key_create_info.block_size= key_info->block_size;
541
 
 
542
429
      if (key_info->flags & HA_USES_COMMENT)
543
430
        key_create_info.comment= key_info->comment;
544
431
 
550
437
          key_type= Key::UNIQUE;
551
438
      }
552
439
      else
553
 
      {
554
440
        key_type= Key::MULTIPLE;
555
 
      }
556
441
 
557
 
      key= new Key(key_type,
558
 
                   key_name,
559
 
                   strlen(key_name),
 
442
      key= new Key(key_type, key_name, strlen(key_name),
560
443
                   &key_create_info,
561
444
                   test(key_info->flags & HA_GENERATED_KEY),
562
445
                   key_parts);
563
446
      new_key_list.push_back(key);
564
447
    }
565
448
  }
566
 
 
567
 
  /* Copy over existing foreign keys */
568
 
  for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
569
 
  {
570
 
    AlterDrop *drop;
571
 
    drop_it.rewind();
572
 
    while ((drop= drop_it++))
573
 
    {
574
 
      if (drop->type == AlterDrop::FOREIGN_KEY &&
575
 
          ! my_strcasecmp(system_charset_info, original_proto.fk_constraint(j).name().c_str(), drop->name))
576
 
      {
577
 
        break;
578
 
      }
579
 
    }
580
 
    if (drop)
581
 
    {
582
 
      drop_it.remove();
583
 
      continue;
584
 
    }
585
 
 
586
 
    message::Table::ForeignKeyConstraint *pfkey= table_message.add_fk_constraint();
587
 
    *pfkey= original_proto.fk_constraint(j);
588
 
  }
589
 
 
590
449
  {
591
450
    Key *key;
592
 
    while ((key= key_it++)) /* Add new keys */
 
451
    while ((key=key_it++))                      // Add new keys
593
452
    {
594
 
      if (key->type == Key::FOREIGN_KEY)
595
 
      {
596
 
        if (((Foreign_key *)key)->validate(new_create_list))
597
 
        {
598
 
          return true;
599
 
        }
600
 
 
601
 
        Foreign_key *fkey= (Foreign_key*)key;
602
 
        add_foreign_key_to_table_message(&table_message,
603
 
                                         fkey->name.str,
604
 
                                         fkey->columns,
605
 
                                         fkey->ref_table,
606
 
                                         fkey->ref_columns,
607
 
                                         fkey->delete_opt,
608
 
                                         fkey->update_opt,
609
 
                                         fkey->match_opt);
610
 
      }
611
 
 
 
453
      if (key->type == Key::FOREIGN_KEY &&
 
454
          ((Foreign_key *)key)->validate(new_create_list))
 
455
        goto err;
612
456
      if (key->type != Key::FOREIGN_KEY)
613
457
        new_key_list.push_back(key);
614
 
 
615
458
      if (key->name.str && is_primary_key_name(key->name.str))
616
459
      {
617
 
        my_error(ER_WRONG_NAME_FOR_INDEX,
618
 
                 MYF(0),
619
 
                 key->name.str);
620
 
        return true;
 
460
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
461
        goto err;
621
462
      }
622
463
    }
623
464
  }
624
465
 
625
 
  /* Fix names of foreign keys being added */
626
 
  for (int j= 0; j < table_message.fk_constraint_size(); j++)
627
 
  {
628
 
    if (! table_message.fk_constraint(j).has_name())
629
 
    {
630
 
      std::string name(table->getMutableShare()->getTableName());
631
 
      char number[20];
632
 
 
633
 
      name.append("_ibfk_");
634
 
      snprintf(number, sizeof(number), "%d", j+1);
635
 
      name.append(number);
636
 
 
637
 
      message::Table::ForeignKeyConstraint *pfkey= table_message.mutable_fk_constraint(j);
638
 
      pfkey->set_name(name);
639
 
    }
640
 
  }
641
 
 
642
466
  if (alter_info->drop_list.elements)
643
467
  {
644
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
645
 
             MYF(0),
 
468
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
646
469
             alter_info->drop_list.head()->name);
647
 
    return true;
 
470
    goto err;
648
471
  }
649
 
 
650
472
  if (alter_info->alter_list.elements)
651
473
  {
652
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
653
 
             MYF(0),
 
474
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
654
475
             alter_info->alter_list.head()->name);
655
 
    return true;
656
 
  }
657
 
 
658
 
  if (not table_message.options().has_comment()
659
 
      && table->getMutableShare()->hasComment())
660
 
  {
661
 
    table_options->set_comment(table->getMutableShare()->getComment());
662
 
  }
663
 
 
664
 
  if (table->getShare()->getType())
665
 
  {
666
 
    table_message.set_type(message::Table::TEMPORARY);
667
 
  }
668
 
 
669
 
  table_message.set_creation_timestamp(table->getShare()->getTableMessage()->creation_timestamp());
670
 
  table_message.set_version(table->getShare()->getTableMessage()->version());
671
 
  table_message.set_uuid(table->getShare()->getTableMessage()->uuid());
 
476
    goto err;
 
477
  }
 
478
 
 
479
  if (! table_proto->options().has_comment()
 
480
      && table->s->hasComment())
 
481
    table_options->set_comment(table->s->getComment());
 
482
 
 
483
  if (table->s->tmp_table)
 
484
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
672
485
 
673
486
  rc= false;
674
487
  alter_info->create_list.swap(new_create_list);
675
488
  alter_info->key_list.swap(new_key_list);
676
 
 
677
 
  size_t num_engine_options= table_message.engine().options_size();
678
 
  size_t original_num_engine_options= original_proto.engine().options_size();
679
 
  for (size_t x= 0; x < original_num_engine_options; ++x)
680
 
  {
681
 
    bool found= false;
682
 
 
683
 
    for (size_t y= 0; y < num_engine_options; ++y)
684
 
    {
685
 
      found= not table_message.engine().options(y).name().compare(original_proto.engine().options(x).name());
686
 
      
687
 
      if (found)
688
 
        break;
689
 
    }
690
 
 
691
 
    if (not found)
692
 
    {
693
 
      message::Engine::Option *opt= table_message.mutable_engine()->add_options();
694
 
 
695
 
      opt->set_name(original_proto.engine().options(x).name());
696
 
      opt->set_state(original_proto.engine().options(x).state());
697
 
    }
698
 
  }
699
 
 
700
 
  drizzled::message::update(table_message);
701
 
 
702
 
  return false;
 
489
err:
 
490
  return(rc);
703
491
}
704
492
 
705
493
/* table_list should contain just one table */
706
 
static int discard_or_import_tablespace(Session *session,
 
494
static int mysql_discard_or_import_tablespace(Session *session,
707
495
                                              TableList *table_list,
708
496
                                              enum tablespace_op_type tablespace_op)
709
497
{
710
498
  Table *table;
711
499
  bool discard;
 
500
  int error;
712
501
 
713
502
  /*
714
503
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
715
504
    ALTER Table
716
505
  */
717
 
  TransactionServices &transaction_services= TransactionServices::singleton();
 
506
 
718
507
  session->set_proc_info("discard_or_import_tablespace");
719
508
 
720
509
  discard= test(tablespace_op == DISCARD_TABLESPACE);
723
512
   We set this flag so that ha_innobase::open and ::external_lock() do
724
513
   not complain when we lock the table
725
514
 */
726
 
  session->setDoingTablespaceOperation(true);
727
 
  if (not (table= session->openTableLock(table_list, TL_WRITE)))
 
515
  session->tablespace_op= true;
 
516
  if (!(table= session->openTableLock(table_list, TL_WRITE)))
728
517
  {
729
 
    session->setDoingTablespaceOperation(false);
 
518
    session->tablespace_op= false;
730
519
    return -1;
731
520
  }
732
521
 
733
 
  int error;
734
 
  do {
735
 
    error= table->cursor->ha_discard_or_import_tablespace(discard);
736
 
 
737
 
    session->set_proc_info("end");
738
 
 
739
 
    if (error)
740
 
      break;
741
 
 
742
 
    /* The ALTER Table is always in its own transaction */
743
 
    error= transaction_services.autocommitOrRollback(*session, false);
744
 
    if (not session->endActiveTransaction())
745
 
      error= 1;
746
 
 
747
 
    if (error)
748
 
      break;
749
 
 
750
 
    write_bin_log(session, *session->getQueryString());
751
 
 
752
 
  } while(0);
753
 
 
754
 
  (void) transaction_services.autocommitOrRollback(*session, error);
755
 
  session->setDoingTablespaceOperation(false);
 
522
  error= table->file->ha_discard_or_import_tablespace(discard);
 
523
 
 
524
  session->set_proc_info("end");
 
525
 
 
526
  if (error)
 
527
    goto err;
 
528
 
 
529
  /* The ALTER Table is always in its own transaction */
 
530
  error = ha_autocommit_or_rollback(session, 0);
 
531
  if (! session->endActiveTransaction())
 
532
    error=1;
 
533
  if (error)
 
534
    goto err;
 
535
  write_bin_log(session, false, session->query, session->query_length);
 
536
 
 
537
err:
 
538
  ha_autocommit_or_rollback(session, error);
 
539
  session->tablespace_op=false;
756
540
 
757
541
  if (error == 0)
758
542
  {
760
544
    return 0;
761
545
  }
762
546
 
763
 
  table->print_error(error, MYF(0));
 
547
  table->file->print_error(error, MYF(0));
764
548
 
765
549
  return -1;
766
550
}
779
563
    false  OK
780
564
    true   Error
781
565
*/
782
 
static bool alter_table_manage_keys(Session *session,
783
 
                                    Table *table, int indexes_were_disabled,
784
 
                                    enum enum_enable_or_disable keys_onoff)
 
566
static bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
 
567
                             enum enum_enable_or_disable keys_onoff)
785
568
{
786
569
  int error= 0;
787
570
  switch (keys_onoff) {
788
571
  case ENABLE:
789
 
    error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
572
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
790
573
    break;
791
574
  case LEAVE_AS_IS:
792
 
    if (not indexes_were_disabled)
 
575
    if (!indexes_were_disabled)
793
576
      break;
794
577
    /* fall-through: disabled indexes */
795
578
  case DISABLE:
796
 
    error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
579
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
797
580
  }
798
581
 
799
582
  if (error == HA_ERR_WRONG_COMMAND)
800
583
  {
801
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
584
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
802
585
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
803
 
                        table->getMutableShare()->getTableName());
 
586
                        table->s->table_name.str);
804
587
    error= 0;
805
 
  }
806
 
  else if (error)
807
 
  {
808
 
    table->print_error(error, MYF(0));
809
 
  }
 
588
  } else if (error)
 
589
    table->file->print_error(error, MYF(0));
810
590
 
811
591
  return(error);
812
592
}
813
593
 
814
 
static bool lockTableIfDifferent(Session &session,
815
 
                                 identifier::Table &original_table_identifier,
816
 
                                 identifier::Table &new_table_identifier,
817
 
                                 Table *name_lock)
818
 
{
819
 
  /* Check that we are not trying to rename to an existing table */
820
 
  if (not (original_table_identifier == new_table_identifier))
821
 
  {
822
 
    if (original_table_identifier.isTmp())
823
 
    {
824
 
 
825
 
      if (session.find_temporary_table(new_table_identifier))
826
 
      {
827
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
828
 
        return false;
829
 
      }
830
 
    }
831
 
    else
832
 
    {
833
 
      if (session.lock_table_name_if_not_cached(new_table_identifier, &name_lock))
834
 
      {
835
 
        return false;
836
 
      }
837
 
 
838
 
      if (not name_lock)
839
 
      {
840
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
841
 
        return false;
842
 
      }
843
 
 
844
 
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
845
 
      {
846
 
        /* Table will be closed by Session::executeCommand() */
847
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
848
 
 
849
 
        {
850
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
851
 
          session.unlink_open_table(name_lock);
852
 
        }
853
 
 
854
 
        return false;
855
 
      }
856
 
    }
857
 
  }
858
 
 
859
 
  return true;
860
 
}
861
 
 
862
594
/**
863
595
  Alter table
864
596
 
865
597
  SYNOPSIS
866
 
    alter_table()
 
598
    mysql_alter_table()
867
599
      session              Thread handle
868
600
      new_db           If there is a RENAME clause
869
601
      new_name         If there is a RENAME clause
872
604
      table_list       The table to change.
873
605
      alter_info       Lists of fields, keys to be changed, added
874
606
                       or dropped.
875
 
      order_num        How many ORDER BY fields has been specified.
 
607
      order_num        How many order_st BY fields has been specified.
876
608
      order            List of fields to order_st BY.
877
609
      ignore           Whether we have ALTER IGNORE Table
878
610
 
884
616
    When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
885
617
    or both, then this function short cuts its operation by renaming
886
618
    the table and/or enabling/disabling the keys. In this case, the FRM is
887
 
    not changed, directly by alter_table. However, if there is a
 
619
    not changed, directly by mysql_alter_table. However, if there is a
888
620
    RENAME + change of a field, or an index, the short cut is not used.
889
621
    See how `create_list` is used to generate the new FRM regarding the
890
622
    structure of the fields. The same is done for the indices of the table.
900
632
    false  OK
901
633
    true   Error
902
634
*/
903
 
 
904
 
static bool internal_alter_table(Session *session,
905
 
                                 Table *table,
906
 
                                 identifier::Table &original_table_identifier,
907
 
                                 identifier::Table &new_table_identifier,
908
 
                                 HA_CREATE_INFO *create_info,
909
 
                                 const message::Table &original_proto,
910
 
                                 message::Table &create_proto,
911
 
                                 TableList *table_list,
912
 
                                 AlterInfo *alter_info,
913
 
                                 uint32_t order_num,
914
 
                                 Order *order,
915
 
                                 bool ignore)
 
635
bool mysql_alter_table(Session *session,
 
636
                       char *new_db,
 
637
                       char *new_name,
 
638
                       HA_CREATE_INFO *create_info,
 
639
                       message::Table *create_proto,
 
640
                       TableList *table_list,
 
641
                       AlterInfo *alter_info,
 
642
                       uint32_t order_num,
 
643
                       order_st *order,
 
644
                       bool ignore)
916
645
{
 
646
  Table *table;
 
647
  Table *new_table= NULL;
 
648
  Table *name_lock= NULL;
 
649
  string new_name_str;
917
650
  int error= 0;
918
651
  char tmp_name[80];
919
652
  char old_name[32];
 
653
  char new_name_buff[FN_REFLEN];
 
654
  char new_alias_buff[FN_REFLEN];
 
655
  char *table_name;
 
656
  char *db;
 
657
  const char *new_alias;
 
658
  char path[FN_REFLEN];
920
659
  ha_rows copied= 0;
921
660
  ha_rows deleted= 0;
922
 
 
923
 
  if (not original_table_identifier.isValid())
924
 
    return true;
925
 
 
926
 
  if (not new_table_identifier.isValid())
927
 
    return true;
 
661
  StorageEngine *old_db_type;
 
662
  StorageEngine *new_db_type;
 
663
  StorageEngine *save_old_db_type;
 
664
  bitset<32> tmp;
 
665
 
 
666
  new_name_buff[0]= '\0';
 
667
 
 
668
  if (table_list && table_list->schema_table)
 
669
  {
 
670
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
671
    return true;
 
672
  }
928
673
 
929
674
  session->set_proc_info("init");
930
675
 
 
676
  /*
 
677
    Assign variables table_name, new_name, db, new_db, path
 
678
    to simplify further comparisons: we want to see if it's a RENAME
 
679
    later just by comparing the pointers, avoiding the need for strcmp.
 
680
  */
 
681
  table_name= table_list->table_name;
 
682
  db= table_list->db;
 
683
  if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
 
684
    new_db= db;
 
685
 
 
686
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
687
  {
 
688
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
689
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
 
690
  }
 
691
 
 
692
  build_table_filename(path, sizeof(path), db, table_name, false);
 
693
 
 
694
  ostringstream oss;
 
695
  oss << drizzle_data_home << "/" << db << "/" << table_name;
 
696
 
 
697
  (void) unpack_filename(new_name_buff, oss.str().c_str());
 
698
 
 
699
  /*
 
700
    If this is just a rename of a view, short cut to the
 
701
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
702
    2) unlock LOCK_open.
 
703
    This is a copy-paste added to make sure
 
704
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
 
705
    as an independent branch in mysql_execute_command. The need
 
706
    for a copy-paste arose because the main code flow of ALTER Table
 
707
    ... RENAME tries to use openTableLock, which does not work for views
 
708
    (openTableLock was never modified to merge table lists of child tables
 
709
    into the main table list, like open_tables does).
 
710
    This code is wrong and will be removed, please do not copy.
 
711
  */
 
712
 
 
713
  if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
 
714
    return true;
 
715
  
931
716
  table->use_all_columns();
932
717
 
933
 
  plugin::StorageEngine *new_engine;
934
 
  plugin::StorageEngine *original_engine;
935
 
 
936
 
  original_engine= table->getMutableShare()->getEngine();
937
 
 
938
 
  if (not create_info->db_type)
939
 
  {
940
 
    create_info->db_type= original_engine;
941
 
  }
942
 
  new_engine= create_info->db_type;
943
 
 
944
 
 
945
 
  create_proto.set_schema(new_table_identifier.getSchemaName());
946
 
  create_proto.set_type(new_table_identifier.getType());
947
 
 
948
 
  /**
949
 
    @todo Have a check on the table definition for FK in the future 
950
 
    to remove the need for the cursor. (aka can_switch_engines())
951
 
  */
952
 
  if (new_engine != original_engine &&
953
 
      not table->cursor->can_switch_engines())
 
718
  /* Check that we are not trying to rename to an existing table */
 
719
  if (new_name)
 
720
  {
 
721
    strcpy(new_name_buff, new_name);
 
722
    strcpy(new_alias_buff, new_name);
 
723
    new_alias= new_alias_buff;
 
724
 
 
725
    my_casedn_str(files_charset_info, new_name_buff);
 
726
    new_alias= new_name; // Create lower case table name
 
727
    my_casedn_str(files_charset_info, new_name);
 
728
 
 
729
    if (new_db == db &&
 
730
        ! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
731
    {
 
732
      /*
 
733
        Source and destination table names are equal: make later check
 
734
        easier.
 
735
      */
 
736
      new_alias= new_name= table_name;
 
737
    }
 
738
    else
 
739
    {
 
740
      if (table->s->tmp_table != NO_TMP_TABLE)
 
741
      {
 
742
        if (session->find_temporary_table(new_db, new_name_buff))
 
743
        {
 
744
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
745
          return true;
 
746
        }
 
747
      }
 
748
      else
 
749
      {
 
750
        if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
 
751
          return true;
 
752
 
 
753
        if (! name_lock)
 
754
        {
 
755
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
756
          return true;
 
757
        }
 
758
 
 
759
        build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
 
760
 
 
761
        if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
 
762
        {
 
763
          /* Table will be closed by Session::executeCommand() */
 
764
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
765
          goto err;
 
766
        }
 
767
      }
 
768
    }
 
769
  }
 
770
  else
 
771
  {
 
772
    new_alias= table_name;
 
773
    new_name= table_name;
 
774
  }
 
775
 
 
776
  old_db_type= table->s->db_type();
 
777
  if (! create_info->db_type)
 
778
  {
 
779
    create_info->db_type= old_db_type;
 
780
  }
 
781
 
 
782
  if (table->s->tmp_table != NO_TMP_TABLE)
 
783
    create_info->options|= HA_LEX_CREATE_TMP_TABLE;
 
784
 
 
785
  if (check_engine(session, new_name, create_info))
 
786
    goto err;
 
787
 
 
788
  new_db_type= create_info->db_type;
 
789
 
 
790
  if (new_db_type != old_db_type &&
 
791
      !table->file->can_switch_engines())
954
792
  {
955
793
    assert(0);
956
794
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
957
 
 
958
 
    return true;
 
795
    goto err;
959
796
  }
960
797
 
961
 
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
 
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
 
798
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
799
    create_info->row_type= table->s->row_type;
 
800
 
 
801
  if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
 
802
      new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
963
803
  {
964
 
    my_error(ER_ILLEGAL_HA, new_table_identifier);
965
 
 
966
 
    return true;
 
804
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
805
    goto err;
967
806
  }
968
807
 
969
808
  session->set_proc_info("setup");
970
 
 
 
809
  
971
810
  /*
972
811
   * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
973
 
 */
 
812
   */
 
813
  tmp.set();
 
814
  tmp.reset(ALTER_RENAME);
 
815
  tmp.reset(ALTER_KEYS_ONOFF);
 
816
  tmp&= alter_info->flags;
 
817
  if (! (tmp.any()) &&
 
818
      ! table->s->tmp_table) // no need to touch frm
974
819
  {
975
 
    bitset<32> tmp;
976
 
 
977
 
    tmp.set();
978
 
    tmp.reset(ALTER_RENAME);
979
 
    tmp.reset(ALTER_KEYS_ONOFF);
980
 
    tmp&= alter_info->flags;
981
 
 
982
 
    if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
983
 
    {
984
 
      switch (alter_info->keys_onoff)
985
 
      {
986
 
      case LEAVE_AS_IS:
987
 
        break;
988
 
 
989
 
      case ENABLE:
990
 
        /*
991
 
          wait_while_table_is_used() ensures that table being altered is
992
 
          opened only by this thread and that Table::TableShare::version
993
 
          of Table object corresponding to this table is 0.
994
 
          The latter guarantees that no DML statement will open this table
995
 
          until ALTER Table finishes (i.e. until close_thread_tables())
996
 
          while the fact that the table is still open gives us protection
997
 
          from concurrent DDL statements.
998
 
        */
999
 
        {
1000
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1001
 
          wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1002
 
        }
1003
 
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1004
 
 
1005
 
        /* COND_refresh will be signaled in close_thread_tables() */
1006
 
        break;
1007
 
 
1008
 
      case DISABLE:
1009
 
        {
1010
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1011
 
          wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1012
 
        }
1013
 
        error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1014
 
 
1015
 
        /* COND_refresh will be signaled in close_thread_tables() */
1016
 
        break;
1017
 
      }
1018
 
 
1019
 
      if (error == HA_ERR_WRONG_COMMAND)
1020
 
      {
1021
 
        error= EE_OK;
1022
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
 
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1024
 
                            table->getAlias());
1025
 
      }
1026
 
 
1027
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
1028
 
      /*
1029
 
        Unlike to the above case close_cached_table() below will remove ALL
1030
 
        instances of Table from table cache (it will also remove table lock
1031
 
        held by this thread). So to make actual table renaming and writing
1032
 
        to binlog atomic we have to put them into the same critical section
1033
 
        protected by table::Cache::singleton().mutex() mutex. This also removes gap for races between
1034
 
        access() and rename_table() calls.
1035
 
      */
1036
 
 
1037
 
      if (not error &&  not (original_table_identifier == new_table_identifier))
1038
 
      {
1039
 
        session->set_proc_info("rename");
1040
 
        /*
1041
 
          Then do a 'simple' rename of the table. First we need to close all
1042
 
          instances of 'source' table.
1043
 
        */
1044
 
        session->close_cached_table(table);
1045
 
        /*
1046
 
          Then, we want check once again that target table does not exist.
1047
 
          Actually the order of these two steps does not matter since
1048
 
          earlier we took name-lock on the target table, so we do them
1049
 
          in this particular order only to be consistent with 5.0, in which
1050
 
          we don't take this name-lock and where this order really matters.
1051
 
          @todo Investigate if we need this access() check at all.
1052
 
        */
1053
 
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1054
 
        {
1055
 
          my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
820
    switch (alter_info->keys_onoff)
 
821
    {
 
822
    case LEAVE_AS_IS:
 
823
      break;
 
824
    case ENABLE:
 
825
      /*
 
826
        wait_while_table_is_used() ensures that table being altered is
 
827
        opened only by this thread and that Table::TableShare::version
 
828
        of Table object corresponding to this table is 0.
 
829
        The latter guarantees that no DML statement will open this table
 
830
        until ALTER Table finishes (i.e. until close_thread_tables())
 
831
        while the fact that the table is still open gives us protection
 
832
        from concurrent DDL statements.
 
833
      */
 
834
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
835
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
836
      pthread_mutex_unlock(&LOCK_open);
 
837
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
838
      /* COND_refresh will be signaled in close_thread_tables() */
 
839
      break;
 
840
    case DISABLE:
 
841
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
842
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
843
      pthread_mutex_unlock(&LOCK_open);
 
844
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
845
      /* COND_refresh will be signaled in close_thread_tables() */
 
846
      break;
 
847
    default:
 
848
      assert(false);
 
849
      error= 0;
 
850
      break;
 
851
    }
 
852
 
 
853
    if (error == HA_ERR_WRONG_COMMAND)
 
854
    {
 
855
      error= 0;
 
856
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
857
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
858
                          table->alias);
 
859
    }
 
860
 
 
861
    pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
 
862
    /*
 
863
      Unlike to the above case close_cached_table() below will remove ALL
 
864
      instances of Table from table cache (it will also remove table lock
 
865
      held by this thread). So to make actual table renaming and writing
 
866
      to binlog atomic we have to put them into the same critical section
 
867
      protected by LOCK_open mutex. This also removes gap for races between
 
868
      access() and mysql_rename_table() calls.
 
869
    */
 
870
 
 
871
    if (error == 0 && 
 
872
        (new_name != table_name || new_db != db))
 
873
    {
 
874
      session->set_proc_info("rename");
 
875
      /*
 
876
        Then do a 'simple' rename of the table. First we need to close all
 
877
        instances of 'source' table.
 
878
      */
 
879
      session->close_cached_table(table);
 
880
      /*
 
881
        Then, we want check once again that target table does not exist.
 
882
        Actually the order of these two steps does not matter since
 
883
        earlier we took name-lock on the target table, so we do them
 
884
        in this particular order only to be consistent with 5.0, in which
 
885
        we don't take this name-lock and where this order really matters.
 
886
        TODO: Investigate if we need this access() check at all.
 
887
      */
 
888
      if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
 
889
      {
 
890
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
891
        error= -1;
 
892
      }
 
893
      else
 
894
      {
 
895
        *fn_ext(new_name)= 0;
 
896
        if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
1056
897
          error= -1;
1057
 
        }
1058
 
        else
1059
 
        {
1060
 
          if (rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
1061
 
          {
1062
 
            error= -1;
1063
 
          }
1064
 
        }
1065
 
      }
1066
 
 
1067
 
      if (error == HA_ERR_WRONG_COMMAND)
1068
 
      {
1069
 
        error= EE_OK;
1070
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1071
 
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1072
 
                            table->getAlias());
1073
 
      }
1074
 
 
1075
 
      if (not error)
1076
 
      {
1077
 
        TransactionServices &transaction_services= TransactionServices::singleton();
1078
 
        transaction_services.allocateNewTransactionId();
1079
 
        write_bin_log(session, *session->getQueryString());
1080
 
        session->my_ok();
1081
 
      }
1082
 
      else if (error > EE_OK) // If we have already set the error, we pass along -1
1083
 
      {
1084
 
        table->print_error(error, MYF(0));
1085
 
      }
1086
 
 
1087
 
      table_list->table= NULL;
1088
 
 
1089
 
      return error;
1090
 
    }
 
898
      }
 
899
    }
 
900
 
 
901
    if (error == HA_ERR_WRONG_COMMAND)
 
902
    {
 
903
      error= 0;
 
904
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
905
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
906
                          table->alias);
 
907
    }
 
908
 
 
909
    if (error == 0)
 
910
    {
 
911
      write_bin_log(session, true, session->query, session->query_length);
 
912
      session->my_ok();
 
913
    }
 
914
    else if (error > 0)
 
915
    {
 
916
      table->file->print_error(error, MYF(0));
 
917
      error= -1;
 
918
    }
 
919
 
 
920
    if (name_lock)
 
921
      session->unlink_open_table(name_lock);
 
922
 
 
923
    pthread_mutex_unlock(&LOCK_open);
 
924
    table_list->table= NULL;
 
925
    return error;
1091
926
  }
1092
927
 
1093
928
  /* We have to do full alter table. */
1094
 
  new_engine= create_info->db_type;
1095
 
 
1096
 
  if (prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
1097
 
  {
1098
 
    return true;
1099
 
  }
1100
 
 
1101
 
  set_table_default_charset(create_info, new_table_identifier.getSchemaName().c_str());
 
929
 
 
930
  /*
 
931
    If the old table had partitions and we are doing ALTER Table ...
 
932
    engine= <new_engine>, the new table must preserve the original
 
933
    partitioning. That means that the new engine is still the
 
934
    partitioning engine, not the engine specified in the parser.
 
935
    This is discovered  in prep_alter_part_table, which in such case
 
936
    updates create_info->db_type.
 
937
    Now we need to update the stack copy of create_info->db_type,
 
938
    as otherwise we won't be able to correctly move the files of the
 
939
    temporary table to the result table files.
 
940
  */
 
941
  new_db_type= create_info->db_type;
 
942
 
 
943
  if (mysql_prepare_alter_table(session, table, create_info, create_proto,
 
944
                                alter_info))
 
945
      goto err;
 
946
 
 
947
  set_table_default_charset(create_info, db);
1102
948
 
1103
949
  alter_info->build_method= HA_BUILD_OFFLINE;
1104
950
 
1105
951
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
952
  
 
953
  /* Safety fix for innodb */
 
954
  my_casedn_str(files_charset_info, tmp_name);
1106
955
 
1107
956
  /* Create a temporary table with the new format */
1108
 
  /**
1109
 
    @note we make an internal temporary table unless the table is a temporary table. In last
1110
 
    case we just use it as is. Neither of these tables require locks in order to  be
1111
 
    filled.
1112
 
  */
1113
 
  identifier::Table new_table_as_temporary(original_table_identifier.getSchemaName(),
1114
 
                                         tmp_name,
1115
 
                                         create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1116
 
                                         message::Table::TEMPORARY);
1117
 
 
1118
 
  /*
1119
 
    Create a table with a temporary name.
1120
 
    We don't log the statement, it will be logged later.
1121
 
  */
1122
 
  create_proto.set_name(new_table_as_temporary.getTableName());
1123
 
  create_proto.mutable_engine()->set_name(create_info->db_type->getName());
1124
 
 
1125
 
  error= create_table(session,
1126
 
                      new_table_as_temporary,
1127
 
                      create_info, create_proto, alter_info, true, 0, false);
1128
 
 
 
957
  error= create_temporary_table(session, table, new_db, tmp_name, create_info, create_proto, alter_info);
1129
958
  if (error != 0)
1130
 
  {
1131
 
    return true;
1132
 
  }
 
959
    goto err;
1133
960
 
1134
961
  /* Open the table so we need to copy the data to it. */
1135
 
  Table *new_table= open_alter_table(session, table, new_table_as_temporary);
1136
 
 
1137
 
 
1138
 
  if (not new_table)
1139
 
  {
1140
 
    plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1141
 
    return true;
1142
 
  }
 
962
  if (table->s->tmp_table)
 
963
  {
 
964
    TableList tbl;
 
965
    tbl.db= new_db;
 
966
    tbl.alias= tmp_name;
 
967
    tbl.table_name= tmp_name;
 
968
 
 
969
    /* Table is in session->temporary_tables */
 
970
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
 
971
  }
 
972
  else
 
973
  {
 
974
    char tmp_path[FN_REFLEN];
 
975
    /* table is a normal table: Create temporary table in same directory */
 
976
    build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
 
977
    /* Open our intermediate table */
 
978
    new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
 
979
  }
 
980
 
 
981
  if (new_table == NULL)
 
982
    goto err1;
1143
983
 
1144
984
  /* Copy the data if necessary. */
1145
 
  {
1146
 
    /* We must not ignore bad input! */
1147
 
    session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;    // calc cuted fields
1148
 
    session->cuted_fields= 0L;
1149
 
    session->set_proc_info("copy to tmp table");
1150
 
    copied= deleted= 0;
1151
 
 
1152
 
    /* We don't want update TIMESTAMP fields during ALTER Table. */
1153
 
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1154
 
    new_table->next_number_field= new_table->found_next_number_field;
1155
 
    error= copy_data_between_tables(session,
1156
 
                                    table,
1157
 
                                    new_table,
1158
 
                                    alter_info->create_list,
1159
 
                                    ignore,
1160
 
                                    order_num,
1161
 
                                    order,
1162
 
                                    &copied,
1163
 
                                    &deleted,
1164
 
                                    alter_info->keys_onoff,
1165
 
                                    alter_info->error_if_not_empty);
1166
 
 
1167
 
    /* We must not ignore bad input! */
1168
 
    assert(session->count_cuted_fields == CHECK_FIELD_ERROR_FOR_NULL);
1169
 
  }
1170
 
 
1171
 
  /* Now we need to resolve what just happened with the data copy. */
1172
 
 
1173
 
  if (error)
1174
 
  {
1175
 
 
1176
 
    /*
1177
 
      No default value was provided for new fields.
1178
 
    */
1179
 
    if (alter_info->error_if_not_empty && session->row_count)
1180
 
    {
1181
 
      my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
1182
 
    }
1183
 
 
1184
 
    if (original_table_identifier.isTmp())
1185
 
    {
1186
 
      if (new_table)
1187
 
      {
1188
 
        /* close_temporary_table() frees the new_table pointer. */
1189
 
        session->close_temporary_table(new_table);
1190
 
      }
1191
 
      else
1192
 
      {
1193
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1194
 
      }
1195
 
 
1196
 
      return true;
1197
 
    }
1198
 
    else
1199
 
    {
1200
 
      if (new_table)
1201
 
      {
1202
 
        /*
1203
 
          Close the intermediate table that will be the new table.
1204
 
          Note that MERGE tables do not have their children attached here.
1205
 
        */
1206
 
        new_table->intern_close_table();
1207
 
        if (new_table->hasShare())
1208
 
        {
1209
 
          delete new_table->getMutableShare();
1210
 
        }
1211
 
 
1212
 
        delete new_table;
1213
 
      }
1214
 
 
1215
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
1216
 
 
1217
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1218
 
 
1219
 
      return true;
1220
 
    }
1221
 
  }
1222
 
  // Temporary table and success
1223
 
  else if (original_table_identifier.isTmp())
1224
 
  {
 
985
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
 
986
  session->cuted_fields= 0L;
 
987
  session->set_proc_info("copy to tmp table");
 
988
  copied= deleted= 0;
 
989
 
 
990
  assert(new_table);
 
991
 
 
992
  /* We don't want update TIMESTAMP fields during ALTER Table. */
 
993
  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
994
  new_table->next_number_field= new_table->found_next_number_field;
 
995
  error= copy_data_between_tables(table, 
 
996
                                  new_table,
 
997
                                  alter_info->create_list, 
 
998
                                  ignore,
 
999
                                  order_num, 
 
1000
                                  order, 
 
1001
                                  &copied, 
 
1002
                                  &deleted,
 
1003
                                  alter_info->keys_onoff,
 
1004
                                  alter_info->error_if_not_empty);
 
1005
 
 
1006
  /* We must not ignore bad input! */
 
1007
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
1008
 
 
1009
  if (table->s->tmp_table != NO_TMP_TABLE)
 
1010
  {
 
1011
    /* We changed a temporary table */
 
1012
    if (error)
 
1013
      goto err1;
 
1014
 
1225
1015
    /* Close lock if this is a transactional table */
1226
1016
    if (session->lock)
1227
1017
    {
1228
 
      session->unlockTables(session->lock);
 
1018
      mysql_unlock_tables(session, session->lock);
1229
1019
      session->lock= 0;
1230
1020
    }
1231
1021
 
1232
1022
    /* Remove link to old table and rename the new one */
1233
 
    session->close_temporary_table(table);
 
1023
    session->close_temporary_table(table, true, true);
1234
1024
 
1235
1025
    /* Should pass the 'new_name' as we store table name in the cache */
1236
 
    new_table->getMutableShare()->setIdentifier(new_table_identifier);
1237
 
 
1238
 
    new_table_identifier.setPath(new_table_as_temporary.getPath());
1239
 
 
1240
 
    if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1241
 
    {
1242
 
      return true;
1243
 
    }
1244
 
  }
1245
 
  // Normal table success
 
1026
    if (new_table->rename_temporary_table(new_db, new_name))
 
1027
      goto err1;
 
1028
    
 
1029
    goto end_temporary;
 
1030
  }
 
1031
 
 
1032
  if (new_table)
 
1033
  {
 
1034
    /*
 
1035
      Close the intermediate table that will be the new table.
 
1036
      Note that MERGE tables do not have their children attached here.
 
1037
    */
 
1038
    new_table->intern_close_table();
 
1039
    free(new_table);
 
1040
  }
 
1041
 
 
1042
  pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
 
1043
  
 
1044
  if (error)
 
1045
  {
 
1046
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
1047
    pthread_mutex_unlock(&LOCK_open);
 
1048
    goto err;
 
1049
  }
 
1050
 
 
1051
  /*
 
1052
    Data is copied. Now we:
 
1053
    1) Wait until all other threads close old version of table.
 
1054
    2) Close instances of table open by this thread and replace them
 
1055
       with exclusive name-locks.
 
1056
    3) Rename the old table to a temp name, rename the new one to the
 
1057
       old name.
 
1058
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
1059
       we reopen new version of table.
 
1060
    5) Write statement to the binary log.
 
1061
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
1062
       remove name-locks from list of open tables and table cache.
 
1063
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
1064
       call to remove name-locks from table cache and list of open table.
 
1065
  */
 
1066
 
 
1067
  session->set_proc_info("rename result table");
 
1068
 
 
1069
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
1070
 
 
1071
  my_casedn_str(files_charset_info, old_name);
 
1072
 
 
1073
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
1074
  session->close_data_files_and_morph_locks(db, table_name);
 
1075
 
 
1076
  error= 0;
 
1077
  save_old_db_type= old_db_type;
 
1078
 
 
1079
  /*
 
1080
    This leads to the storage engine (SE) not being notified for renames in
 
1081
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
1082
    more. If we have an intermediate table, then we notify the SE that
 
1083
    it should become the actual table. Later, we will recycle the old table.
 
1084
    However, in case of ALTER Table RENAME there might be no intermediate
 
1085
    table. This is when the old and new tables are compatible, according to
 
1086
    compare_table(). Then, we need one additional call to
 
1087
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
1088
    actual rename in the SE and the FRM is not touched. Note that, if the
 
1089
    table is renamed and the SE is also changed, then an intermediate table
 
1090
    is created and the additional call will not take place.
 
1091
  */
 
1092
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
 
1093
  {
 
1094
    error= 1;
 
1095
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
1096
  }
1246
1097
  else
1247
1098
  {
1248
 
    if (new_table)
1249
 
    {
1250
 
      /*
1251
 
        Close the intermediate table that will be the new table.
1252
 
        Note that MERGE tables do not have their children attached here.
1253
 
      */
1254
 
      new_table->intern_close_table();
1255
 
 
1256
 
      if (new_table->hasShare())
1257
 
      {
1258
 
        delete new_table->getMutableShare();
1259
 
      }
1260
 
 
1261
 
      delete new_table;
1262
 
    }
1263
 
 
1264
 
    {
1265
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* ALTER TABLE */
1266
 
      /*
1267
 
        Data is copied. Now we:
1268
 
        1) Wait until all other threads close old version of table.
1269
 
        2) Close instances of table open by this thread and replace them
1270
 
        with exclusive name-locks.
1271
 
        3) Rename the old table to a temp name, rename the new one to the
1272
 
        old name.
1273
 
        4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1274
 
        we reopen new version of table.
1275
 
        5) Write statement to the binary log.
1276
 
        6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1277
 
        remove name-locks from list of open tables and table cache.
1278
 
        7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1279
 
        call to remove name-locks from table cache and list of open table.
1280
 
      */
1281
 
 
1282
 
      session->set_proc_info("rename result table");
1283
 
 
1284
 
      snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1285
 
 
1286
 
      my_casedn_str(files_charset_info, old_name);
1287
 
 
1288
 
      wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1289
 
      session->close_data_files_and_morph_locks(original_table_identifier);
1290
 
 
1291
 
      assert(not error);
1292
 
 
1293
 
      /*
1294
 
        This leads to the storage engine (SE) not being notified for renames in
1295
 
        rename_table(), because we just juggle with the FRM and nothing
1296
 
        more. If we have an intermediate table, then we notify the SE that
1297
 
        it should become the actual table. Later, we will recycle the old table.
1298
 
        However, in case of ALTER Table RENAME there might be no intermediate
1299
 
        table. This is when the old and new tables are compatible, according to
1300
 
        compare_table(). Then, we need one additional call to
1301
 
      */
1302
 
      identifier::Table original_table_to_drop(original_table_identifier.getSchemaName(),
1303
 
                                             old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1304
 
                                             message::Table::TEMPORARY);
1305
 
 
1306
 
      drizzled::error_t rename_error= EE_OK;
1307
 
      if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1308
 
      {
1309
 
        error= ER_ERROR_ON_RENAME;
1310
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1311
 
      }
1312
 
      else
1313
 
      {
1314
 
        if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1315
 
        {
1316
 
          /* Try to get everything back. */
1317
 
          rename_error= ER_ERROR_ON_RENAME;
1318
 
 
1319
 
          plugin::StorageEngine::dropTable(*session, new_table_identifier);
1320
 
 
1321
 
          plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1322
 
 
1323
 
          rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1324
 
        }
1325
 
        else
1326
 
        {
1327
 
          plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1328
 
        }
1329
 
      }
1330
 
 
1331
 
      if (rename_error)
1332
 
      {
1333
 
        /*
1334
 
          An error happened while we were holding exclusive name-lock on table
1335
 
          being altered. To be safe under LOCK TABLES we should remove placeholders
1336
 
          from list of open tables list and table cache.
1337
 
        */
1338
 
        session->unlink_open_table(table);
1339
 
 
1340
 
        return true;
1341
 
      }
1342
 
    }
1343
 
 
1344
 
    session->set_proc_info("end");
1345
 
 
1346
 
    write_bin_log(session, *session->getQueryString());
1347
 
    table_list->table= NULL;
1348
 
  }
1349
 
 
 
1099
    if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
 
1100
    {
 
1101
      /* Try to get everything back. */
 
1102
      error= 1;
 
1103
      quick_rm_table(new_db_type, new_db, new_alias, false);
 
1104
      quick_rm_table(new_db_type, new_db, tmp_name, true);
 
1105
      mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
 
1106
    }
 
1107
  }
 
1108
 
 
1109
  if (error)
 
1110
  {
 
1111
    /* This shouldn't happen. But let us play it safe. */
 
1112
    goto err_with_placeholders;
 
1113
  }
 
1114
 
 
1115
  quick_rm_table(old_db_type, db, old_name, true);
 
1116
 
 
1117
  pthread_mutex_unlock(&LOCK_open);
 
1118
 
 
1119
  session->set_proc_info("end");
 
1120
 
 
1121
  write_bin_log(session, true, session->query, session->query_length);
 
1122
 
 
1123
  if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
 
1124
  {
 
1125
    /*
 
1126
      For the alter table to be properly flushed to the logs, we
 
1127
      have to open the new table.  If not, we get a problem on server
 
1128
      shutdown. But we do not need to attach MERGE children.
 
1129
    */
 
1130
    char table_path[FN_REFLEN];
 
1131
    Table *t_table;
 
1132
    build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
 
1133
    t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
 
1134
    if (t_table)
 
1135
    {
 
1136
      t_table->intern_close_table();
 
1137
      free(t_table);
 
1138
    }
 
1139
    else
 
1140
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
 
1141
 
 
1142
    ha_flush_logs(old_db_type);
 
1143
  }
 
1144
  table_list->table= NULL;
 
1145
 
 
1146
end_temporary:
1350
1147
  /*
1351
1148
   * Field::store() may have called my_error().  If this is 
1352
1149
   * the case, we must not send an ok packet, since 
1353
1150
   * Diagnostics_area::is_set() will fail an assert.
1354
 
 */
1355
 
  if (session->is_error())
 
1151
   */
 
1152
  if (! session->is_error())
 
1153
  {
 
1154
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
1155
            (ulong) (copied + deleted), (ulong) deleted,
 
1156
            (ulong) session->cuted_fields);
 
1157
    session->my_ok(copied + deleted, 0, 0L, tmp_name);
 
1158
    session->some_tables_deleted=0;
 
1159
    return false;
 
1160
  }
 
1161
  else
1356
1162
  {
1357
1163
    /* my_error() was called.  Return true (which means error...) */
1358
1164
    return true;
1359
1165
  }
1360
1166
 
1361
 
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1362
 
           (ulong) (copied + deleted), (ulong) deleted,
1363
 
           (ulong) session->cuted_fields);
1364
 
  session->my_ok(copied + deleted, 0, 0L, tmp_name);
1365
 
  session->some_tables_deleted= false;
1366
 
 
1367
 
  return false;
1368
 
}
1369
 
 
1370
 
bool alter_table(Session *session,
1371
 
                 identifier::Table &original_table_identifier,
1372
 
                 identifier::Table &new_table_identifier,
1373
 
                 HA_CREATE_INFO *create_info,
1374
 
                 const message::Table &original_proto,
1375
 
                 message::Table &create_proto,
1376
 
                 TableList *table_list,
1377
 
                 AlterInfo *alter_info,
1378
 
                 uint32_t order_num,
1379
 
                 Order *order,
1380
 
                 bool ignore)
1381
 
{
1382
 
  bool error;
1383
 
  Table *table;
1384
 
 
1385
 
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
1386
 
  {
1387
 
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
1388
 
    return discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
1389
 
  }
1390
 
 
1391
 
  session->set_proc_info("init");
1392
 
 
1393
 
  if (not (table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
1394
 
    return true;
1395
 
 
1396
 
  session->set_proc_info("gained write lock on table");
1397
 
 
1398
 
  /* 
1399
 
    Check that we are not trying to rename to an existing table,
1400
 
    if one existed we get a lock, if we can't we error.
1401
 
  */
1402
 
  {
1403
 
    Table *name_lock= NULL;
1404
 
 
1405
 
    if (not lockTableIfDifferent(*session, original_table_identifier, new_table_identifier, name_lock))
1406
 
    {
1407
 
      return true;
1408
 
    }
1409
 
 
1410
 
    error= internal_alter_table(session,
1411
 
                                table,
1412
 
                                original_table_identifier,
1413
 
                                new_table_identifier,
1414
 
                                create_info,
1415
 
                                original_proto,
1416
 
                                create_proto,
1417
 
                                table_list,
1418
 
                                alter_info,
1419
 
                                order_num,
1420
 
                                order,
1421
 
                                ignore);
1422
 
 
1423
 
    if (name_lock)
1424
 
    {
1425
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
1426
 
      session->unlink_open_table(name_lock);
1427
 
    }
1428
 
  }
1429
 
 
1430
 
  return error;
1431
 
}
1432
 
/* alter_table */
 
1167
err1:
 
1168
  if (new_table)
 
1169
  {
 
1170
    /* close_temporary_table() frees the new_table pointer. */
 
1171
    session->close_temporary_table(new_table, true, true);
 
1172
  }
 
1173
  else
 
1174
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
1175
 
 
1176
err:
 
1177
  /*
 
1178
    No default value was provided for a DATE/DATETIME field, the
 
1179
    current sql_mode doesn't allow the '0000-00-00' value and
 
1180
    the table to be altered isn't empty.
 
1181
    Report error here.
 
1182
  */
 
1183
  if (alter_info->error_if_not_empty && session->row_count)
 
1184
  {
 
1185
    const char *f_val= 0;
 
1186
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
1187
    switch (alter_info->datetime_field->sql_type)
 
1188
    {
 
1189
      case DRIZZLE_TYPE_DATE:
 
1190
        f_val= "0000-00-00";
 
1191
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
1192
        break;
 
1193
      case DRIZZLE_TYPE_DATETIME:
 
1194
        f_val= "0000-00-00 00:00:00";
 
1195
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
1196
        break;
 
1197
      default:
 
1198
        /* Shouldn't get here. */
 
1199
        assert(0);
 
1200
    }
 
1201
    bool save_abort_on_warning= session->abort_on_warning;
 
1202
    session->abort_on_warning= true;
 
1203
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1204
                                 f_val, strlength(f_val), t_type,
 
1205
                                 alter_info->datetime_field->field_name);
 
1206
    session->abort_on_warning= save_abort_on_warning;
 
1207
  }
 
1208
  if (name_lock)
 
1209
  {
 
1210
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
 
1211
    session->unlink_open_table(name_lock);
 
1212
    pthread_mutex_unlock(&LOCK_open);
 
1213
  }
 
1214
  return true;
 
1215
 
 
1216
err_with_placeholders:
 
1217
  /*
 
1218
    An error happened while we were holding exclusive name-lock on table
 
1219
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
1220
    from list of open tables list and table cache.
 
1221
  */
 
1222
  session->unlink_open_table(table);
 
1223
  if (name_lock)
 
1224
    session->unlink_open_table(name_lock);
 
1225
  pthread_mutex_unlock(&LOCK_open);
 
1226
  return true;
 
1227
}
 
1228
/* mysql_alter_table */
1433
1229
 
1434
1230
static int
1435
 
copy_data_between_tables(Session *session,
1436
 
                         Table *from, Table *to,
1437
 
                         List<CreateField> &create,
 
1231
copy_data_between_tables(Table *from,Table *to,
 
1232
                         List<CreateField> &create,
1438
1233
                         bool ignore,
1439
 
                         uint32_t order_num, Order *order,
1440
 
                         ha_rows *copied,
1441
 
                         ha_rows *deleted,
 
1234
                         uint32_t order_num, order_st *order,
 
1235
                         ha_rows *copied,
 
1236
                         ha_rows *deleted,
1442
1237
                         enum enum_enable_or_disable keys_onoff,
1443
1238
                         bool error_if_not_empty)
1444
1239
{
1445
 
  int error= 0;
 
1240
  int error;
1446
1241
  CopyField *copy,*copy_end;
1447
1242
  ulong found_count,delete_count;
 
1243
  Session *session= current_session;
1448
1244
  uint32_t length= 0;
1449
 
  SortField *sortorder;
1450
 
  ReadRecord info;
 
1245
  SORT_FIELD *sortorder;
 
1246
  READ_RECORD info;
1451
1247
  TableList   tables;
1452
1248
  List<Item>   fields;
1453
1249
  List<Item>   all_fields;
1461
1257
 
1462
1258
    This needs to be done before external_lock
1463
1259
  */
1464
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1465
 
 
1466
 
  /* 
1467
 
   * LP Bug #552420 
1468
 
   *
1469
 
   * Since open_temporary_table() doesn't invoke lockTables(), we
1470
 
   * don't get the usual automatic call to StorageEngine::startStatement(), so
1471
 
   * we manually call it here...
1472
 
   */
1473
 
  to->getMutableShare()->getEngine()->startStatement(session);
1474
 
 
1475
 
  if (!(copy= new CopyField[to->getShare()->sizeFields()]))
 
1260
  error= ha_enable_transaction(session, false);
 
1261
  if (error)
1476
1262
    return -1;
1477
1263
 
1478
 
  if (to->cursor->ha_external_lock(session, F_WRLCK))
 
1264
  if (!(copy= new CopyField[to->s->fields]))
 
1265
    return -1;                          /* purecov: inspected */
 
1266
 
 
1267
  if (to->file->ha_external_lock(session, F_WRLCK))
1479
1268
    return -1;
1480
1269
 
1481
1270
  /* We need external lock before we can disable/enable keys */
1482
 
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
 
1271
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
1483
1272
 
1484
1273
  /* We can abort alter table for any table type */
1485
 
  session->setAbortOnWarning(not ignore);
 
1274
  session->abort_on_warning= !ignore;
1486
1275
 
1487
 
  from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
 
  to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
 
1276
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
1277
  to->file->ha_start_bulk_insert(from->file->stats.records);
1489
1278
 
1490
1279
  List_iterator<CreateField> it(create);
1491
1280
  CreateField *def;
1492
 
  copy_end= copy;
1493
 
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
 
1281
  copy_end=copy;
 
1282
  for (Field **ptr=to->field ; *ptr ; ptr++)
1494
1283
  {
1495
1284
    def=it++;
1496
1285
    if (def->field)
1505
1294
 
1506
1295
  found_count=delete_count=0;
1507
1296
 
1508
 
  do
1509
 
  {
1510
 
    if (order)
1511
 
    {
1512
 
      if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
1513
 
      {
1514
 
        char warn_buff[DRIZZLE_ERRMSG_SIZE];
1515
 
        snprintf(warn_buff, sizeof(warn_buff),
1516
 
                 _("order_st BY ignored because there is a user-defined clustered "
1517
 
                   "index in the table '%-.192s'"),
1518
 
                 from->getMutableShare()->getTableName());
1519
 
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1520
 
                     warn_buff);
1521
 
      }
 
1297
  if (order)
 
1298
  {
 
1299
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
 
1300
    {
 
1301
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
1302
      snprintf(warn_buff, sizeof(warn_buff),
 
1303
               _("order_st BY ignored because there is a user-defined clustered "
 
1304
                 "index in the table '%-.192s'"),
 
1305
               from->s->table_name.str);
 
1306
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1307
                   warn_buff);
 
1308
    }
 
1309
    else
 
1310
    {
 
1311
      from->sort.io_cache= new IO_CACHE;
 
1312
      memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
 
1313
 
 
1314
      memset(&tables, 0, sizeof(tables));
 
1315
      tables.table= from;
 
1316
      tables.alias= tables.table_name= from->s->table_name.str;
 
1317
      tables.db= from->s->db.str;
 
1318
      error= 1;
 
1319
 
 
1320
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
1321
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
1322
                      &tables, fields, all_fields, order) ||
 
1323
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
1324
          (from->sort.found_records= filesort(session, from, sortorder, length,
 
1325
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
1326
                                              1, &examined_rows)) ==
 
1327
          HA_POS_ERROR)
 
1328
        goto err;
 
1329
    }
 
1330
  };
 
1331
 
 
1332
  /* Tell handler that we have values for all columns in the to table */
 
1333
  to->use_all_columns();
 
1334
  init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
 
1335
  if (ignore)
 
1336
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1337
  session->row_count= 0;
 
1338
  to->restoreRecordAsDefault();        // Create empty record
 
1339
  while (!(error=info.read_record(&info)))
 
1340
  {
 
1341
    if (session->killed)
 
1342
    {
 
1343
      session->send_kill_message();
 
1344
      error= 1;
 
1345
      break;
 
1346
    }
 
1347
    session->row_count++;
 
1348
    /* Return error if source table isn't empty. */
 
1349
    if (error_if_not_empty)
 
1350
    {
 
1351
      error= 1;
 
1352
      break;
 
1353
    }
 
1354
    if (to->next_number_field)
 
1355
    {
 
1356
      if (auto_increment_field_copied)
 
1357
        to->auto_increment_field_not_null= true;
1522
1358
      else
1523
 
      {
1524
 
        FileSort filesort(*session);
1525
 
        from->sort.io_cache= new internal::IO_CACHE;
1526
 
 
1527
 
        tables.table= from;
1528
 
        tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
1529
 
        tables.alias= const_cast<char *>(tables.getTableName());
1530
 
        tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1531
 
        error= 1;
1532
 
 
1533
 
        if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1534
 
            setup_order(session, session->lex->select_lex.ref_pointer_array,
1535
 
                        &tables, fields, all_fields, order) ||
1536
 
            !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1537
 
            (from->sort.found_records= filesort.run(from, sortorder, length,
1538
 
                                                    (optimizer::SqlSelect *) 0, HA_POS_ERROR,
1539
 
                                                    1, examined_rows)) == HA_POS_ERROR)
1540
 
        {
1541
 
          break;
1542
 
        }
1543
 
      }
1544
 
    }
1545
 
 
1546
 
    /* Tell handler that we have values for all columns in the to table */
1547
 
    to->use_all_columns();
1548
 
 
1549
 
    error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
 
1359
        to->next_number_field->reset();
 
1360
    }
 
1361
 
 
1362
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
1363
    {
 
1364
      copy_ptr->do_copy(copy_ptr);
 
1365
    }
 
1366
    prev_insert_id= to->file->next_insert_id;
 
1367
    error=to->file->ha_write_row(to->record[0]);
 
1368
    to->auto_increment_field_not_null= false;
1550
1369
    if (error)
1551
1370
    {
1552
 
      to->print_error(errno, MYF(0));
1553
 
 
1554
 
      break;
1555
 
    }
1556
 
 
1557
 
    if (ignore)
1558
 
    {
1559
 
      to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1560
 
    }
1561
 
 
1562
 
    session->row_count= 0;
1563
 
    to->restoreRecordAsDefault();        // Create empty record
1564
 
    while (not (error=info.read_record(&info)))
1565
 
    {
1566
 
      if (session->getKilled())
1567
 
      {
1568
 
        session->send_kill_message();
1569
 
        error= 1;
1570
 
        break;
1571
 
      }
1572
 
      session->row_count++;
1573
 
      /* Return error if source table isn't empty. */
1574
 
      if (error_if_not_empty)
1575
 
      {
1576
 
        error= 1;
1577
 
        break;
1578
 
      }
1579
 
      if (to->next_number_field)
1580
 
      {
1581
 
        if (auto_increment_field_copied)
1582
 
          to->auto_increment_field_not_null= true;
1583
 
        else
1584
 
          to->next_number_field->reset();
1585
 
      }
1586
 
 
1587
 
      for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1588
 
      {
1589
 
        if (not copy->to_field->hasDefault() and copy->from_null_ptr and  *copy->from_null_ptr & copy->from_bit)
1590
 
        {
1591
 
          copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1592
 
                                      ER_WARN_DATA_TRUNCATED, 1);
1593
 
          copy->to_field->reset();
1594
 
          error= 1;
1595
 
          break;
1596
 
        }
1597
 
 
1598
 
        copy_ptr->do_copy(copy_ptr);
1599
 
      }
1600
 
 
1601
 
      if (error)
1602
 
      {
1603
 
        break;
1604
 
      }
1605
 
 
1606
 
      prev_insert_id= to->cursor->next_insert_id;
1607
 
      error= to->cursor->insertRecord(to->record[0]);
1608
 
      to->auto_increment_field_not_null= false;
1609
 
 
1610
 
      if (error)
1611
 
      { 
1612
 
        if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1613
 
        { 
1614
 
          to->print_error(error, MYF(0));
1615
 
          break;
1616
 
        }
1617
 
        to->cursor->restore_auto_increment(prev_insert_id);
1618
 
        delete_count++;
1619
 
      }
1620
 
      else
1621
 
      {
1622
 
        found_count++;
1623
 
      }
1624
 
    }
1625
 
 
1626
 
    info.end_read_record();
1627
 
    from->free_io_cache();
1628
 
    delete [] copy;                             // This is never 0
1629
 
 
1630
 
    if (to->cursor->ha_end_bulk_insert() && error <= 0)
1631
 
    {
1632
 
      to->print_error(errno, MYF(0));
1633
 
      error= 1;
1634
 
    }
1635
 
    to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1636
 
 
1637
 
    /*
1638
 
      Ensure that the new table is saved properly to disk so that we
1639
 
      can do a rename
1640
 
    */
1641
 
    if (transaction_services.autocommitOrRollback(*session, false))
1642
 
      error= 1;
1643
 
 
1644
 
    if (not session->endActiveTransaction())
1645
 
      error= 1;
1646
 
 
1647
 
  } while (0);
1648
 
 
1649
 
  session->setAbortOnWarning(false);
 
1371
      if (!ignore ||
 
1372
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
1373
      {
 
1374
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
1375
         {
 
1376
           uint32_t key_nr= to->file->get_dup_key(error);
 
1377
           if ((int) key_nr >= 0)
 
1378
           {
 
1379
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
1380
             if (key_nr == 0 &&
 
1381
                 (to->key_info[0].key_part[0].field->flags &
 
1382
                  AUTO_INCREMENT_FLAG))
 
1383
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
1384
             to->file->print_keydup_error(key_nr, err_msg);
 
1385
             break;
 
1386
           }
 
1387
         }
 
1388
 
 
1389
        to->file->print_error(error,MYF(0));
 
1390
        break;
 
1391
      }
 
1392
      to->file->restore_auto_increment(prev_insert_id);
 
1393
      delete_count++;
 
1394
    }
 
1395
    else
 
1396
      found_count++;
 
1397
  }
 
1398
  end_read_record(&info);
 
1399
  from->free_io_cache();
 
1400
  delete [] copy;                               // This is never 0
 
1401
 
 
1402
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
1403
  {
 
1404
    to->file->print_error(my_errno,MYF(0));
 
1405
    error=1;
 
1406
  }
 
1407
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1408
 
 
1409
  if (ha_enable_transaction(session, true))
 
1410
  {
 
1411
    error= 1;
 
1412
    goto err;
 
1413
  }
 
1414
 
 
1415
  /*
 
1416
    Ensure that the new table is saved properly to disk so that we
 
1417
    can do a rename
 
1418
  */
 
1419
  if (ha_autocommit_or_rollback(session, 0))
 
1420
    error=1;
 
1421
  if (! session->endActiveTransaction())
 
1422
    error=1;
 
1423
 
 
1424
 err:
 
1425
  session->abort_on_warning= 0;
1650
1426
  from->free_io_cache();
1651
1427
  *copied= found_count;
1652
1428
  *deleted=delete_count;
1653
 
  to->cursor->ha_release_auto_increment();
1654
 
 
1655
 
  if (to->cursor->ha_external_lock(session, F_UNLCK))
1656
 
  {
 
1429
  to->file->ha_release_auto_increment();
 
1430
  if (to->file->ha_external_lock(session,F_UNLCK))
1657
1431
    error=1;
1658
 
  }
1659
 
 
1660
1432
  return(error > 0 ? -1 : 0);
1661
1433
}
1662
1434
 
1663
 
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
1664
 
{
1665
 
  Table *new_table;
1666
 
 
1667
 
  /* Open the table so we need to copy the data to it. */
1668
 
  if (table->getShare()->getType())
1669
 
  {
1670
 
    TableList tbl;
1671
 
    tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
1672
 
    tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1673
 
    tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
1674
 
 
1675
 
    /* Table is in session->temporary_tables */
1676
 
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
1677
 
  }
 
1435
static int
 
1436
create_temporary_table(Session *session,
 
1437
                       Table *table,
 
1438
                       char *new_db,
 
1439
                       char *tmp_name,
 
1440
                       HA_CREATE_INFO *create_info,
 
1441
                       message::Table *create_proto,
 
1442
                       AlterInfo *alter_info)
 
1443
{
 
1444
  int error;
 
1445
  StorageEngine *old_db_type, *new_db_type;
 
1446
  old_db_type= table->s->db_type();
 
1447
  new_db_type= create_info->db_type;
 
1448
  /*
 
1449
    Create a table with a temporary name.
 
1450
    We don't log the statement, it will be logged later.
 
1451
  */
 
1452
  create_proto->set_name(tmp_name);
 
1453
  create_proto->set_type(message::Table::TEMPORARY);
 
1454
 
 
1455
  message::Table::StorageEngine *protoengine;
 
1456
  protoengine= create_proto->mutable_engine();
 
1457
  protoengine->set_name(new_db_type->getName());
 
1458
 
 
1459
  error= mysql_create_table(session, new_db, tmp_name,
 
1460
                            create_info, create_proto, alter_info, 1, 0);
 
1461
 
 
1462
  return(error);
 
1463
}
 
1464
 
 
1465
/** @TODO This will soon die. */
 
1466
bool mysql_create_like_schema_frm(Session* session,
 
1467
                                  TableList* schema_table,
 
1468
                                  HA_CREATE_INFO *create_info,
 
1469
                                  message::Table* table_proto)
 
1470
{
 
1471
  HA_CREATE_INFO local_create_info;
 
1472
  AlterInfo alter_info;
 
1473
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
1474
  uint32_t keys= schema_table->table->s->keys;
 
1475
  uint32_t db_options= 0;
 
1476
 
 
1477
  memset(&local_create_info, 0, sizeof(local_create_info));
 
1478
  local_create_info.db_type= schema_table->table->s->db_type();
 
1479
  local_create_info.row_type= schema_table->table->s->row_type;
 
1480
  local_create_info.default_table_charset=default_charset_info;
 
1481
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
1482
  alter_info.flags.set(ALTER_RECREATE);
 
1483
  schema_table->table->use_all_columns();
 
1484
  if (mysql_prepare_alter_table(session, schema_table->table,
 
1485
                                &local_create_info, table_proto, &alter_info))
 
1486
    return true;
 
1487
 
 
1488
  /* I_S tables are created with MAX_ROWS for some efficiency drive.
 
1489
     When CREATE LIKE, we don't want to keep it coming across */
 
1490
  message::Table::TableOptions *table_options;
 
1491
  table_options= table_proto->mutable_options();
 
1492
  table_options->clear_max_rows();
 
1493
 
 
1494
  if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
 
1495
                                 tmp_table, &db_options,
 
1496
                                 schema_table->table->file,
 
1497
                                 &schema_table->table->s->key_info, &keys, 0))
 
1498
    return true;
 
1499
 
 
1500
  table_proto->set_name("system_stupid_i_s_fix_nonsense");
 
1501
  if(tmp_table)
 
1502
    table_proto->set_type(message::Table::TEMPORARY);
1678
1503
  else
 
1504
    table_proto->set_type(message::Table::STANDARD);
 
1505
 
1679
1506
  {
1680
 
    /* Open our intermediate table */
1681
 
    new_table= session->open_temporary_table(identifier, false);
 
1507
    message::Table::StorageEngine *protoengine;
 
1508
    protoengine= table_proto->mutable_engine();
 
1509
 
 
1510
    StorageEngine *engine= local_create_info.db_type;
 
1511
 
 
1512
    protoengine->set_name(engine->getName());
1682
1513
  }
1683
1514
 
1684
 
  return new_table;
 
1515
  if (fill_table_proto(table_proto, "system_stupid_i_s_fix_nonsense",
 
1516
                       alter_info.create_list, &local_create_info,
 
1517
                       keys, schema_table->table->s->key_info))
 
1518
    return true;
 
1519
 
 
1520
  return false;
1685
1521
}
1686
 
 
1687
 
} /* namespace drizzled */