~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Marisa Plumb
  • Date: 2010-12-04 02:38:29 UTC
  • mto: This revision was merged to the branch mainline in revision 1984.
  • Revision ID: marisa.plumb@gmail.com-20101204023829-2khzxh30wxi256db
updates to a few sql docs 

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>
 
21
#include "config.h"
22
22
 
23
23
#include <fcntl.h>
24
24
 
25
25
#include <sstream>
26
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
 
 
33
 
 
34
 
#include <drizzled/gettext.h>
35
 
#include <drizzled/data_home.h>
36
 
#include <drizzled/sql_table.h>
37
 
#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>
 
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
 
 
33
 
 
34
#include "drizzled/gettext.h"
 
35
#include "drizzled/data_home.h"
 
36
#include "drizzled/sql_table.h"
 
37
#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
 
 
45
#include "drizzled/transaction_services.h"
 
46
 
 
47
#include "drizzled/filesort.h"
 
48
 
 
49
#include "drizzled/message.h"
52
50
 
53
51
using namespace std;
54
52
 
68
66
                                    enum enum_enable_or_disable keys_onoff,
69
67
                                    bool error_if_not_empty);
70
68
 
71
 
static bool prepare_alter_table(Session *session,
 
69
static bool mysql_prepare_alter_table(Session *session,
72
70
                                      Table *table,
73
71
                                      HA_CREATE_INFO *create_info,
74
72
                                      const message::Table &original_proto,
75
73
                                      message::Table &table_message,
76
74
                                      AlterInfo *alter_info);
77
75
 
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->getLex()->sql_command= SQLCOM_ALTER_TABLE;
86
 
  (void)ident;
87
 
  alter_info.build_method= build_arg;
88
 
}
89
 
 
90
 
} // namespace statement
 
76
static int create_temporary_table(Session *session,
 
77
                                  TableIdentifier &identifier,
 
78
                                  HA_CREATE_INFO *create_info,
 
79
                                  message::Table &create_message,
 
80
                                  AlterInfo *alter_info);
 
81
 
 
82
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier);
91
83
 
92
84
bool statement::AlterTable::execute()
93
85
{
94
 
  TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
95
 
  TableList *all_tables= getSession()->getLex()->query_tables;
 
86
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
 
87
  TableList *all_tables= session->lex->query_tables;
96
88
  assert(first_table == all_tables && first_table != 0);
97
 
  Select_Lex *select_lex= &getSession()->getLex()->select_lex;
 
89
  Select_Lex *select_lex= &session->lex->select_lex;
98
90
  bool need_start_waiting= false;
99
91
 
100
 
  is_engine_set= not createTableMessage().engine().name().empty();
101
 
 
102
92
  if (is_engine_set)
103
93
  {
104
 
    create_info().db_type= 
105
 
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
 
94
    create_info.db_type= 
 
95
      plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
106
96
 
107
 
    if (create_info().db_type == NULL)
 
97
    if (create_info.db_type == NULL)
108
98
    {
109
 
      my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
 
99
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
 
100
               create_table_message.engine().name().c_str());
110
101
 
111
102
      return true;
112
103
    }
118
109
  /* 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
110
  message::table::shared_ptr original_table_message;
120
111
  {
121
 
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
 
    if (not (original_table_message= plugin::StorageEngine::getTableMessage(*getSession(), identifier)))
 
112
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
113
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
123
114
    {
124
 
      my_error(ER_BAD_TABLE_ERROR, identifier);
 
115
      my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
125
116
      return true;
126
117
    }
127
118
 
128
 
    if (not  create_info().db_type)
 
119
    if (not  create_info.db_type)
129
120
    {
130
 
      create_info().db_type= 
131
 
        plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
 
121
      create_info.db_type= 
 
122
        plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
132
123
 
133
 
      if (not create_info().db_type)
 
124
      if (not create_info.db_type)
134
125
      {
135
 
        my_error(ER_BAD_TABLE_ERROR, identifier);
 
126
        my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
136
127
        return true;
137
128
      }
138
129
    }
139
130
  }
140
131
 
141
132
  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;
 
133
  {
 
134
    return true;
 
135
  }
 
136
 
 
137
  /* ALTER TABLE ends previous transaction */
 
138
  if (not session->endActiveTransaction())
 
139
  {
 
140
    return true;
 
141
  }
 
142
 
 
143
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
 
144
  {
 
145
    return true;
 
146
  }
152
147
 
153
148
  bool res;
154
149
  if (original_table_message->type() == message::Table::STANDARD )
155
150
  {
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()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName());
 
151
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
152
    TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
 
153
                                   session->lex->name.str ? session->lex->name.str : first_table->getTableName());
159
154
 
160
 
    res= alter_table(getSession(), 
 
155
    res= alter_table(session, 
161
156
                     identifier,
162
157
                     new_identifier,
163
 
                     &create_info(),
 
158
                     &create_info,
164
159
                     *original_table_message,
165
 
                     createTableMessage(),
 
160
                     create_table_message,
166
161
                     first_table,
167
162
                     &alter_info,
168
163
                     select_lex->order_list.elements,
169
164
                     (Order *) select_lex->order_list.first,
170
 
                     getSession()->getLex()->ignore);
 
165
                     session->lex->ignore);
171
166
  }
172
167
  else
173
168
  {
174
 
    identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
 
    Table *table= getSession()->find_temporary_table(catch22);
 
169
    TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
 
170
    Table *table= session->find_temporary_table(catch22);
176
171
    assert(table);
177
172
    {
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()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName(),
181
 
                                       table->getMutableShare()->getPath());
 
173
      TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
 
174
      TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
 
175
                                     session->lex->name.str ? session->lex->name.str : first_table->getTableName(),
 
176
                                     table->getMutableShare()->getPath());
182
177
 
183
 
      res= alter_table(getSession(), 
 
178
      res= alter_table(session, 
184
179
                       identifier,
185
180
                       new_identifier,
186
 
                       &create_info(),
 
181
                       &create_info,
187
182
                       *original_table_message,
188
 
                       createTableMessage(),
 
183
                       create_table_message,
189
184
                       first_table,
190
185
                       &alter_info,
191
186
                       select_lex->order_list.elements,
192
187
                       (Order *) select_lex->order_list.first,
193
 
                       getSession()->getLex()->ignore);
 
188
                       session->lex->ignore);
194
189
    }
195
190
  }
196
191
 
198
193
     Release the protection against the global read lock and wake
199
194
     everyone, who might want to set a global read lock.
200
195
   */
201
 
  getSession()->startWaitingGlobalReadLock();
 
196
  session->startWaitingGlobalReadLock();
202
197
 
203
198
  return res;
204
199
}
244
239
                 Table instructions
245
240
  @retval false  success
246
241
*/
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)
 
242
static bool mysql_prepare_alter_table(Session *session,
 
243
                                      Table *table,
 
244
                                      HA_CREATE_INFO *create_info,
 
245
                                      const message::Table &original_proto,
 
246
                                      message::Table &table_message,
 
247
                                      AlterInfo *alter_info)
253
248
{
254
249
  /* New column definitions are added here */
255
250
  List<CreateField> new_create_list;
256
251
  /* New key definitions are added here */
257
252
  List<Key> new_key_list;
258
 
  List<AlterDrop>::iterator drop_it(alter_info->drop_list.begin());
259
 
  List<CreateField>::iterator def_it(alter_info->create_list.begin());
260
 
  List<AlterColumn>::iterator alter_it(alter_info->alter_list.begin());
261
 
  List<Key>::iterator key_it(alter_info->key_list.begin());
262
 
  List<CreateField>::iterator find_it(new_create_list.begin());
263
 
  List<CreateField>::iterator field_it(new_create_list.begin());
 
253
  List_iterator<AlterDrop> drop_it(alter_info->drop_list);
 
254
  List_iterator<CreateField> def_it(alter_info->create_list);
 
255
  List_iterator<AlterColumn> alter_it(alter_info->alter_list);
 
256
  List_iterator<Key> key_it(alter_info->key_list);
 
257
  List_iterator<CreateField> find_it(new_create_list);
 
258
  List_iterator<CreateField> field_it(new_create_list);
264
259
  List<Key_part_spec> key_parts;
265
260
  uint32_t used_fields= create_info->used_fields;
266
261
  KeyInfo *key_info= table->key_info;
270
265
  message::Table::TableOptions *table_options;
271
266
  table_options= table_message.mutable_options();
272
267
 
273
 
  if (not (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
268
  if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
274
269
    create_info->default_table_charset= table->getShare()->table_charset;
275
 
 
276
 
  if (not (used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
270
  if (! (used_fields & HA_CREATE_USED_AUTO) &&
 
271
      table->found_next_number_field)
277
272
  {
278
273
    /* Table has an autoincrement, copy value to new table */
279
274
    table->cursor->info(HA_STATUS_AUTO);
281
276
    if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
282
277
      table_options->set_has_user_set_auto_increment_value(false);
283
278
  }
284
 
 
285
279
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
286
280
  CreateField *def;
287
281
 
288
282
  /* First collect all fields from table which isn't in drop_list */
 
283
  Field **f_ptr;
289
284
  Field *field;
290
 
  for (Field **f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
 
285
  for (f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
291
286
  {
292
287
    /* Check if field should be dropped */
293
288
    AlterDrop *drop;
294
 
    drop_it= alter_info->drop_list.begin();
 
289
    drop_it.rewind();
295
290
    while ((drop= drop_it++))
296
291
    {
297
292
      if (drop->type == AlterDrop::COLUMN &&
307
302
        break;
308
303
      }
309
304
    }
310
 
 
311
305
    if (drop)
312
306
    {
313
307
      drop_it.remove();
318
312
    field->setReadSet();
319
313
 
320
314
    /* Check if field is changed */
321
 
    def_it= alter_info->create_list.begin();
 
315
    def_it.rewind();
322
316
    while ((def= def_it++))
323
317
    {
324
318
      if (def->change &&
325
319
          ! my_strcasecmp(system_charset_info, field->field_name, def->change))
326
320
              break;
327
321
    }
328
 
 
329
322
    if (def)
330
323
    {
331
324
      /* Field is changed */
344
337
      */
345
338
      def= new CreateField(field, field);
346
339
      new_create_list.push_back(def);
347
 
      alter_it= alter_info->alter_list.begin(); /* Change default if ALTER */
 
340
      alter_it.rewind(); /* Change default if ALTER */
348
341
      AlterColumn *alter;
349
 
 
350
342
      while ((alter= alter_it++))
351
343
      {
352
344
        if (! my_strcasecmp(system_charset_info,field->field_name, alter->name))
353
345
          break;
354
346
      }
355
 
 
356
347
      if (alter)
357
348
      {
358
349
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
359
350
        {
360
351
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
361
 
          return true;
 
352
                goto err;
362
353
        }
363
 
 
364
354
        if ((def->def= alter->def))
365
355
        {
366
356
          /* Use new default */
367
357
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
368
358
        }
369
359
        else
370
 
        {
371
360
          def->flags|= NO_DEFAULT_VALUE_FLAG;
372
 
        }
373
361
        alter_it.remove();
374
362
      }
375
363
    }
376
364
  }
377
 
 
378
 
  def_it= alter_info->create_list.begin();
 
365
  def_it.rewind();
379
366
  while ((def= def_it++)) /* Add new columns */
380
367
  {
381
368
    if (def->change && ! def->field)
382
369
    {
383
370
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
384
 
      return true;
 
371
      goto err;
385
372
    }
386
373
    /*
387
 
      If we have been given a field which has no default value, and is not null then we need to bail.
 
374
      Check that the DATE/DATETIME not null field we are going to add is
 
375
      either has a default value or the '0000-00-00' is allowed by the
 
376
      set sql mode.
 
377
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
378
      flag to allow ALTER Table only if the table to be altered is empty.
388
379
    */
389
 
    if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
 
380
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
381
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
382
        ! alter_info->datetime_field &&
 
383
        ! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)))
390
384
    {
 
385
      alter_info->datetime_field= def;
391
386
      alter_info->error_if_not_empty= true;
392
387
    }
393
388
    if (! def->after)
394
 
    {
395
389
      new_create_list.push_back(def);
396
 
    }
397
390
    else if (def->after == first_keyword)
398
 
    {
399
391
      new_create_list.push_front(def);
400
 
    }
401
392
    else
402
393
    {
403
394
      CreateField *find;
404
 
      find_it= new_create_list.begin();
405
 
 
 
395
      find_it.rewind();
406
396
      while ((find= find_it++)) /* Add new columns */
407
397
      {
408
 
        if (not my_strcasecmp(system_charset_info,def->after, find->field_name))
 
398
        if (! my_strcasecmp(system_charset_info,def->after, find->field_name))
409
399
          break;
410
400
      }
411
 
 
412
 
      if (not find)
 
401
      if (! find)
413
402
      {
414
403
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
415
 
        return true;
 
404
        goto err;
416
405
      }
417
 
 
418
406
      find_it.after(def); /* Put element after this */
419
 
 
420
407
      /*
421
408
        XXX: hack for Bug#28427.
422
409
        If column order has changed, force OFFLINE ALTER Table
429
416
      */
430
417
      if (alter_info->build_method == HA_BUILD_ONLINE)
431
418
      {
432
 
        my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
433
 
        return true;
 
419
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
 
420
        goto err;
434
421
      }
435
 
 
436
422
      alter_info->build_method= HA_BUILD_OFFLINE;
437
423
    }
438
424
  }
439
 
 
440
425
  if (alter_info->alter_list.elements)
441
426
  {
442
427
    my_error(ER_BAD_FIELD_ERROR,
443
428
             MYF(0),
444
429
             alter_info->alter_list.head()->name,
445
430
             table->getMutableShare()->getTableName());
446
 
    return true;
 
431
    goto err;
447
432
  }
448
 
 
449
 
  if (not new_create_list.elements)
 
433
  if (! new_create_list.elements)
450
434
  {
451
435
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
436
               ER(ER_CANT_REMOVE_ALL_FIELDS),
453
437
               MYF(0));
454
 
    return true;
 
438
    goto err;
455
439
  }
456
440
 
457
441
  /*
462
446
  {
463
447
    char *key_name= key_info->name;
464
448
    AlterDrop *drop;
465
 
 
466
 
    drop_it= alter_info->drop_list.begin();
 
449
    drop_it.rewind();
467
450
    while ((drop= drop_it++))
468
451
    {
469
452
      if (drop->type == AlterDrop::KEY &&
470
453
          ! my_strcasecmp(system_charset_info, key_name, drop->name))
471
454
        break;
472
455
    }
473
 
 
474
456
    if (drop)
475
457
    {
476
458
      drop_it.remove();
478
460
    }
479
461
 
480
462
    KeyPartInfo *key_part= key_info->key_part;
481
 
    key_parts.clear();
 
463
    key_parts.empty();
482
464
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
483
465
    {
484
466
      if (! key_part->field)
486
468
 
487
469
      const char *key_part_name= key_part->field->field_name;
488
470
      CreateField *cfield;
489
 
      field_it= new_create_list.begin();
 
471
      field_it.rewind();
490
472
      while ((cfield= field_it++))
491
473
      {
492
474
        if (cfield->change)
493
475
        {
494
 
          if (not my_strcasecmp(system_charset_info, key_part_name, cfield->change))
 
476
          if (! my_strcasecmp(system_charset_info, key_part_name, cfield->change))
495
477
            break;
496
478
        }
497
 
        else if (not my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
 
479
        else if (! my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
498
480
          break;
499
481
      }
500
 
 
501
 
      if (not cfield)
 
482
      if (! cfield)
502
483
              continue; /* Field is removed */
503
484
      
504
485
      uint32_t key_part_length= key_part->length;
530
511
    }
531
512
    if (key_parts.elements)
532
513
    {
533
 
      key_create_information_st key_create_info= default_key_create_info;
 
514
      KEY_CREATE_INFO key_create_info;
534
515
      Key *key;
535
 
      Key::Keytype key_type;
 
516
      enum Key::Keytype key_type;
 
517
      memset(&key_create_info, 0, sizeof(key_create_info));
536
518
 
537
519
      key_create_info.algorithm= key_info->algorithm;
538
 
 
539
520
      if (key_info->flags & HA_USES_BLOCK_SIZE)
540
521
        key_create_info.block_size= key_info->block_size;
541
 
 
542
522
      if (key_info->flags & HA_USES_COMMENT)
543
523
        key_create_info.comment= key_info->comment;
544
524
 
550
530
          key_type= Key::UNIQUE;
551
531
      }
552
532
      else
553
 
      {
554
533
        key_type= Key::MULTIPLE;
555
 
      }
556
534
 
557
535
      key= new Key(key_type,
558
536
                   key_name,
565
543
  }
566
544
 
567
545
  /* Copy over existing foreign keys */
568
 
  for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
 
546
  for (int j= 0; j < original_proto.fk_constraint_size(); j++)
569
547
  {
570
548
    AlterDrop *drop;
571
 
    drop_it= alter_info->drop_list.begin();
 
549
    drop_it.rewind();
572
550
    while ((drop= drop_it++))
573
551
    {
574
552
      if (drop->type == AlterDrop::FOREIGN_KEY &&
594
572
      if (key->type == Key::FOREIGN_KEY)
595
573
      {
596
574
        if (((Foreign_key *)key)->validate(new_create_list))
597
 
        {
598
 
          return true;
599
 
        }
 
575
          goto err;
600
576
 
601
577
        Foreign_key *fkey= (Foreign_key*)key;
602
578
        add_foreign_key_to_table_message(&table_message,
617
593
        my_error(ER_WRONG_NAME_FOR_INDEX,
618
594
                 MYF(0),
619
595
                 key->name.str);
620
 
        return true;
 
596
        goto err;
621
597
      }
622
598
    }
623
599
  }
644
620
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
645
621
             MYF(0),
646
622
             alter_info->drop_list.head()->name);
647
 
    return true;
 
623
    goto err;
648
624
  }
649
 
 
650
625
  if (alter_info->alter_list.elements)
651
626
  {
652
627
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
653
628
             MYF(0),
654
629
             alter_info->alter_list.head()->name);
655
 
    return true;
 
630
    goto err;
656
631
  }
657
632
 
658
633
  if (not table_message.options().has_comment()
659
634
      && table->getMutableShare()->hasComment())
660
 
  {
661
635
    table_options->set_comment(table->getMutableShare()->getComment());
662
 
  }
663
636
 
664
637
  if (table->getShare()->getType())
665
638
  {
666
639
    table_message.set_type(message::Table::TEMPORARY);
667
640
  }
668
641
 
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());
 
642
  table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
 
643
  table_message.set_version(table->getShare()->getTableProto()->version());
 
644
  table_message.set_uuid(table->getShare()->getTableProto()->uuid());
672
645
 
673
646
  rc= false;
674
647
  alter_info->create_list.swap(new_create_list);
675
648
  alter_info->key_list.swap(new_key_list);
 
649
err:
676
650
 
677
651
  size_t num_engine_options= table_message.engine().options_size();
678
652
  size_t original_num_engine_options= original_proto.engine().options_size();
699
673
 
700
674
  drizzled::message::update(table_message);
701
675
 
702
 
  return false;
 
676
  return rc;
703
677
}
704
678
 
705
679
/* table_list should contain just one table */
706
 
static int discard_or_import_tablespace(Session *session,
 
680
static int mysql_discard_or_import_tablespace(Session *session,
707
681
                                              TableList *table_list,
708
682
                                              enum tablespace_op_type tablespace_op)
709
683
{
710
684
  Table *table;
711
685
  bool discard;
 
686
  int error;
712
687
 
713
688
  /*
714
689
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
715
690
    ALTER Table
716
691
  */
 
692
 
717
693
  TransactionServices &transaction_services= TransactionServices::singleton();
718
694
  session->set_proc_info("discard_or_import_tablespace");
719
695
 
723
699
   We set this flag so that ha_innobase::open and ::external_lock() do
724
700
   not complain when we lock the table
725
701
 */
726
 
  session->setDoingTablespaceOperation(true);
727
 
  if (not (table= session->openTableLock(table_list, TL_WRITE)))
 
702
  session->tablespace_op= true;
 
703
  if (!(table= session->openTableLock(table_list, TL_WRITE)))
728
704
  {
729
 
    session->setDoingTablespaceOperation(false);
 
705
    session->tablespace_op= false;
730
706
    return -1;
731
707
  }
732
708
 
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);
 
709
  error= table->cursor->ha_discard_or_import_tablespace(discard);
 
710
 
 
711
  session->set_proc_info("end");
 
712
 
 
713
  if (error)
 
714
    goto err;
 
715
 
 
716
  /* The ALTER Table is always in its own transaction */
 
717
  error= transaction_services.autocommitOrRollback(session, false);
 
718
  if (not session->endActiveTransaction())
 
719
    error=1;
 
720
 
 
721
  if (error)
 
722
    goto err;
 
723
 
 
724
  write_bin_log(session, *session->getQueryString());
 
725
 
 
726
err:
 
727
  (void) transaction_services.autocommitOrRollback(session, error);
 
728
  session->tablespace_op=false;
756
729
 
757
730
  if (error == 0)
758
731
  {
802
775
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
803
776
                        table->getMutableShare()->getTableName());
804
777
    error= 0;
805
 
  }
806
 
  else if (error)
807
 
  {
 
778
  } else if (error)
808
779
    table->print_error(error, MYF(0));
809
 
  }
810
780
 
811
781
  return(error);
812
782
}
813
783
 
814
784
static bool lockTableIfDifferent(Session &session,
815
 
                                 identifier::Table &original_table_identifier,
816
 
                                 identifier::Table &new_table_identifier,
 
785
                                 TableIdentifier &original_table_identifier,
 
786
                                 TableIdentifier &new_table_identifier,
817
787
                                 Table *name_lock)
818
788
{
819
789
  /* Check that we are not trying to rename to an existing table */
824
794
 
825
795
      if (session.find_temporary_table(new_table_identifier))
826
796
      {
827
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
797
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
828
798
        return false;
829
799
      }
830
800
    }
837
807
 
838
808
      if (not name_lock)
839
809
      {
840
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
810
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
841
811
        return false;
842
812
      }
843
813
 
844
814
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
845
815
      {
846
816
        /* Table will be closed by Session::executeCommand() */
847
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
817
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
848
818
 
849
 
        {
850
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
851
 
          session.unlink_open_table(name_lock);
852
 
        }
 
819
        LOCK_open.lock(); /* ALTER TABLe */
 
820
        session.unlink_open_table(name_lock);
 
821
        LOCK_open.unlock();
853
822
 
854
823
        return false;
855
824
      }
903
872
 
904
873
static bool internal_alter_table(Session *session,
905
874
                                 Table *table,
906
 
                                 identifier::Table &original_table_identifier,
907
 
                                 identifier::Table &new_table_identifier,
 
875
                                 TableIdentifier &original_table_identifier,
 
876
                                 TableIdentifier &new_table_identifier,
908
877
                                 HA_CREATE_INFO *create_info,
909
878
                                 const message::Table &original_proto,
910
879
                                 message::Table &create_proto,
920
889
  ha_rows copied= 0;
921
890
  ha_rows deleted= 0;
922
891
 
923
 
  if (not original_table_identifier.isValid())
924
 
    return true;
925
 
 
926
 
  if (not new_table_identifier.isValid())
927
 
    return true;
928
 
 
929
892
  session->set_proc_info("init");
930
893
 
931
894
  table->use_all_columns();
961
924
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
925
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
963
926
  {
964
 
    my_error(ER_ILLEGAL_HA, new_table_identifier);
 
927
    my_error(ER_ILLEGAL_HA, MYF(0), new_table_identifier.getSQLPath().c_str());
965
928
 
966
929
    return true;
967
930
  }
979
942
    tmp.reset(ALTER_KEYS_ONOFF);
980
943
    tmp&= alter_info->flags;
981
944
 
982
 
    if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
 
945
    if (! (tmp.any()) && ! table->getShare()->getType()) // no need to touch frm
983
946
    {
984
947
      switch (alter_info->keys_onoff)
985
948
      {
986
949
      case LEAVE_AS_IS:
987
950
        break;
988
 
 
989
951
      case ENABLE:
990
952
        /*
991
953
          wait_while_table_is_used() ensures that table being altered is
996
958
          while the fact that the table is still open gives us protection
997
959
          from concurrent DDL statements.
998
960
        */
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
 
        }
 
961
        LOCK_open.lock(); /* DDL wait for/blocker */
 
962
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
963
        LOCK_open.unlock();
1003
964
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1004
 
 
1005
965
        /* COND_refresh will be signaled in close_thread_tables() */
1006
966
        break;
1007
 
 
1008
967
      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
 
 
 
968
        LOCK_open.lock(); /* DDL wait for/blocker */
 
969
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
970
        LOCK_open.unlock();
 
971
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1015
972
        /* COND_refresh will be signaled in close_thread_tables() */
1016
973
        break;
 
974
      default:
 
975
        assert(false);
 
976
        error= 0;
 
977
        break;
1017
978
      }
1018
979
 
1019
980
      if (error == HA_ERR_WRONG_COMMAND)
1020
981
      {
1021
 
        error= EE_OK;
 
982
        error= 0;
1022
983
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
984
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1024
985
                            table->getAlias());
1025
986
      }
1026
987
 
1027
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
 
988
      LOCK_open.lock(); /* Lock to remove all instances of table from table cache before ALTER */
1028
989
      /*
1029
990
        Unlike to the above case close_cached_table() below will remove ALL
1030
991
        instances of Table from table cache (it will also remove table lock
1031
992
        held by this thread). So to make actual table renaming and writing
1032
993
        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.
 
994
        protected by LOCK_open mutex. This also removes gap for races between
 
995
        access() and mysql_rename_table() calls.
1035
996
      */
1036
997
 
1037
 
      if (not error &&  not (original_table_identifier == new_table_identifier))
 
998
      if (error == 0 &&  not (original_table_identifier == new_table_identifier))
1038
999
      {
1039
1000
        session->set_proc_info("rename");
1040
1001
        /*
1052
1013
        */
1053
1014
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1054
1015
        {
1055
 
          my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
1016
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
1056
1017
          error= -1;
1057
1018
        }
1058
1019
        else
1059
1020
        {
1060
 
          if (rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
 
1021
          if (mysql_rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
1061
1022
          {
1062
1023
            error= -1;
1063
1024
          }
1066
1027
 
1067
1028
      if (error == HA_ERR_WRONG_COMMAND)
1068
1029
      {
1069
 
        error= EE_OK;
 
1030
        error= 0;
1070
1031
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1071
1032
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1072
1033
                            table->getAlias());
1073
1034
      }
1074
1035
 
1075
 
      if (not error)
 
1036
      if (error == 0)
1076
1037
      {
1077
1038
        TransactionServices &transaction_services= TransactionServices::singleton();
1078
1039
        transaction_services.allocateNewTransactionId();
1079
1040
        write_bin_log(session, *session->getQueryString());
1080
1041
        session->my_ok();
1081
1042
      }
1082
 
      else if (error > EE_OK) // If we have already set the error, we pass along -1
 
1043
      else if (error > 0)
1083
1044
      {
1084
1045
        table->print_error(error, MYF(0));
 
1046
        error= -1;
1085
1047
      }
1086
1048
 
 
1049
      LOCK_open.unlock();
1087
1050
      table_list->table= NULL;
1088
1051
 
1089
1052
      return error;
1093
1056
  /* We have to do full alter table. */
1094
1057
  new_engine= create_info->db_type;
1095
1058
 
1096
 
  if (prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
 
1059
  if (mysql_prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
1097
1060
  {
1098
1061
    return true;
1099
1062
  }
1110
1073
    case we just use it as is. Neither of these tables require locks in order to  be
1111
1074
    filled.
1112
1075
  */
1113
 
  identifier::Table new_table_as_temporary(original_table_identifier.getSchemaName(),
 
1076
  TableIdentifier new_table_as_temporary(original_table_identifier.getSchemaName(),
1114
1077
                                         tmp_name,
1115
1078
                                         create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1116
1079
                                         message::Table::TEMPORARY);
1117
1080
 
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);
 
1081
  error= create_temporary_table(session, new_table_as_temporary, create_info, create_proto, alter_info);
1128
1082
 
1129
1083
  if (error != 0)
1130
1084
  {
1137
1091
 
1138
1092
  if (not new_table)
1139
1093
  {
1140
 
    plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1094
    quick_rm_table(*session, new_table_as_temporary);
1141
1095
    return true;
1142
1096
  }
1143
1097
 
1174
1128
  {
1175
1129
 
1176
1130
    /*
1177
 
      No default value was provided for new fields.
 
1131
      No default value was provided for a DATE/DATETIME field, the
 
1132
      current sql_mode doesn't allow the '0000-00-00' value and
 
1133
      the table to be altered isn't empty.
 
1134
      Report error here.
1178
1135
    */
1179
1136
    if (alter_info->error_if_not_empty && session->row_count)
1180
1137
    {
1181
 
      my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
 
1138
      const char *f_val= 0;
 
1139
      enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
1140
 
 
1141
      switch (alter_info->datetime_field->sql_type)
 
1142
      {
 
1143
      case DRIZZLE_TYPE_DATE:
 
1144
        f_val= "0000-00-00";
 
1145
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
1146
        break;
 
1147
      case DRIZZLE_TYPE_DATETIME:
 
1148
        f_val= "0000-00-00 00:00:00";
 
1149
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
1150
        break;
 
1151
      default:
 
1152
        /* Shouldn't get here. */
 
1153
        assert(0);
 
1154
      }
 
1155
      bool save_abort_on_warning= session->abort_on_warning;
 
1156
      session->abort_on_warning= true;
 
1157
      make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1158
                                   f_val, internal::strlength(f_val), t_type,
 
1159
                                   alter_info->datetime_field->field_name);
 
1160
      session->abort_on_warning= save_abort_on_warning;
1182
1161
    }
1183
1162
 
1184
1163
    if (original_table_identifier.isTmp())
1190
1169
      }
1191
1170
      else
1192
1171
      {
1193
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1172
        quick_rm_table(*session, new_table_as_temporary);
1194
1173
      }
1195
1174
 
1196
1175
      return true;
1212
1191
        delete new_table;
1213
1192
      }
1214
1193
 
1215
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1194
      LOCK_open.lock(); /* ALTER TABLE */
1216
1195
 
1217
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1196
      quick_rm_table(*session, new_table_as_temporary);
 
1197
      LOCK_open.unlock();
1218
1198
 
1219
1199
      return true;
1220
1200
    }
1237
1217
 
1238
1218
    new_table_identifier.setPath(new_table_as_temporary.getPath());
1239
1219
 
1240
 
    if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
 
1220
    if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1241
1221
    {
1242
1222
      return true;
1243
1223
    }
1261
1241
      delete new_table;
1262
1242
    }
1263
1243
 
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))
 
1244
    LOCK_open.lock(); /* ALTER TABLE */
 
1245
 
 
1246
    /*
 
1247
      Data is copied. Now we:
 
1248
      1) Wait until all other threads close old version of table.
 
1249
      2) Close instances of table open by this thread and replace them
 
1250
      with exclusive name-locks.
 
1251
      3) Rename the old table to a temp name, rename the new one to the
 
1252
      old name.
 
1253
      4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
1254
      we reopen new version of table.
 
1255
      5) Write statement to the binary log.
 
1256
      6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
1257
      remove name-locks from list of open tables and table cache.
 
1258
      7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
1259
      call to remove name-locks from table cache and list of open table.
 
1260
    */
 
1261
 
 
1262
    session->set_proc_info("rename result table");
 
1263
 
 
1264
    snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
1265
 
 
1266
    my_casedn_str(files_charset_info, old_name);
 
1267
 
 
1268
    wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
1269
    session->close_data_files_and_morph_locks(original_table_identifier);
 
1270
 
 
1271
    error= 0;
 
1272
 
 
1273
    /*
 
1274
      This leads to the storage engine (SE) not being notified for renames in
 
1275
      mysql_rename_table(), because we just juggle with the FRM and nothing
 
1276
      more. If we have an intermediate table, then we notify the SE that
 
1277
      it should become the actual table. Later, we will recycle the old table.
 
1278
      However, in case of ALTER Table RENAME there might be no intermediate
 
1279
      table. This is when the old and new tables are compatible, according to
 
1280
      compare_table(). Then, we need one additional call to
 
1281
    */
 
1282
    TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
 
1283
                                           old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
 
1284
                                         message::Table::TEMPORARY);
 
1285
 
 
1286
    if (mysql_rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
 
1287
    {
 
1288
      error= 1;
 
1289
      quick_rm_table(*session, new_table_as_temporary);
 
1290
    }
 
1291
    else
 
1292
    {
 
1293
      if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1308
1294
      {
1309
 
        error= ER_ERROR_ON_RENAME;
1310
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1295
        /* Try to get everything back. */
 
1296
        error= 1;
 
1297
 
 
1298
        quick_rm_table(*session, new_table_identifier);
 
1299
 
 
1300
        quick_rm_table(*session, new_table_as_temporary);
 
1301
 
 
1302
        mysql_rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1311
1303
      }
1312
1304
      else
1313
1305
      {
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
 
    }
 
1306
        quick_rm_table(*session, original_table_to_drop);
 
1307
      }
 
1308
    }
 
1309
 
 
1310
    if (error)
 
1311
    {
 
1312
      /*
 
1313
        An error happened while we were holding exclusive name-lock on table
 
1314
        being altered. To be safe under LOCK TABLES we should remove placeholders
 
1315
        from list of open tables list and table cache.
 
1316
      */
 
1317
      session->unlink_open_table(table);
 
1318
      LOCK_open.unlock();
 
1319
 
 
1320
      return true;
 
1321
    }
 
1322
 
 
1323
    LOCK_open.unlock();
1343
1324
 
1344
1325
    session->set_proc_info("end");
1345
1326
 
1362
1343
           (ulong) (copied + deleted), (ulong) deleted,
1363
1344
           (ulong) session->cuted_fields);
1364
1345
  session->my_ok(copied + deleted, 0, 0L, tmp_name);
1365
 
  session->some_tables_deleted= false;
 
1346
  session->some_tables_deleted= 0;
1366
1347
 
1367
1348
  return false;
1368
1349
}
1369
1350
 
1370
1351
bool alter_table(Session *session,
1371
 
                 identifier::Table &original_table_identifier,
1372
 
                 identifier::Table &new_table_identifier,
 
1352
                 TableIdentifier &original_table_identifier,
 
1353
                 TableIdentifier &new_table_identifier,
1373
1354
                 HA_CREATE_INFO *create_info,
1374
1355
                 const message::Table &original_proto,
1375
1356
                 message::Table &create_proto,
1385
1366
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
1386
1367
  {
1387
1368
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
1388
 
    return discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
 
1369
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
1389
1370
  }
1390
1371
 
1391
1372
  session->set_proc_info("init");
1422
1403
 
1423
1404
    if (name_lock)
1424
1405
    {
1425
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1406
      LOCK_open.lock(); /* ALTER TABLe */
1426
1407
      session->unlink_open_table(name_lock);
 
1408
      LOCK_open.unlock();
1427
1409
    }
1428
1410
  }
1429
1411
 
1482
1464
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
1483
1465
 
1484
1466
  /* We can abort alter table for any table type */
1485
 
  session->setAbortOnWarning(not ignore);
 
1467
  session->abort_on_warning= !ignore;
1486
1468
 
1487
1469
  from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
1470
  to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
1489
1471
 
1490
 
  List<CreateField>::iterator it(create.begin());
 
1472
  List_iterator<CreateField> it(create);
1491
1473
  CreateField *def;
1492
 
  copy_end= copy;
 
1474
  copy_end=copy;
1493
1475
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
1494
1476
  {
1495
1477
    def=it++;
1505
1487
 
1506
1488
  found_count=delete_count=0;
1507
1489
 
1508
 
  do
 
1490
  if (order)
1509
1491
  {
1510
 
    if (order)
1511
 
    {
1512
 
      if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1492
    if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1493
    {
 
1494
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
1495
      snprintf(warn_buff, sizeof(warn_buff),
 
1496
               _("order_st BY ignored because there is a user-defined clustered "
 
1497
                 "index in the table '%-.192s'"),
 
1498
               from->getMutableShare()->getTableName());
 
1499
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1500
                   warn_buff);
 
1501
    }
 
1502
    else
 
1503
    {
 
1504
      FileSort filesort(*session);
 
1505
      from->sort.io_cache= new internal::IO_CACHE;
 
1506
 
 
1507
      memset(&tables, 0, sizeof(tables));
 
1508
      tables.table= from;
 
1509
      tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
 
1510
      tables.alias= const_cast<char *>(tables.getTableName());
 
1511
      tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
 
1512
      error= 1;
 
1513
 
 
1514
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
1515
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
1516
                      &tables, fields, all_fields, order) ||
 
1517
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
1518
          (from->sort.found_records= filesort.run(from, sortorder, length,
 
1519
                                                  (optimizer::SqlSelect *) 0, HA_POS_ERROR,
 
1520
                                                  1, examined_rows)) == HA_POS_ERROR)
1513
1521
      {
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);
 
1522
        goto err;
1521
1523
      }
 
1524
    }
 
1525
  }
 
1526
 
 
1527
  /* Tell handler that we have values for all columns in the to table */
 
1528
  to->use_all_columns();
 
1529
  info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
 
1530
  if (ignore)
 
1531
    to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1532
  session->row_count= 0;
 
1533
  to->restoreRecordAsDefault();        // Create empty record
 
1534
  while (!(error=info.read_record(&info)))
 
1535
  {
 
1536
    if (session->getKilled())
 
1537
    {
 
1538
      session->send_kill_message();
 
1539
      error= 1;
 
1540
      break;
 
1541
    }
 
1542
    session->row_count++;
 
1543
    /* Return error if source table isn't empty. */
 
1544
    if (error_if_not_empty)
 
1545
    {
 
1546
      error= 1;
 
1547
      break;
 
1548
    }
 
1549
    if (to->next_number_field)
 
1550
    {
 
1551
      if (auto_increment_field_copied)
 
1552
        to->auto_increment_field_not_null= true;
1522
1553
      else
1523
 
      {
1524
 
        FileSort filesort(*session);
1525
 
        from->sort.io_cache= new internal::IO_CACHE;
1526
 
 
1527
 
        tables.table= from;
1528
 
        tables.setTableName(from->getMutableShare()->getTableName());
1529
 
        tables.alias= tables.getTableName();
1530
 
        tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1531
 
        error= 1;
1532
 
 
1533
 
        if (session->getLex()->select_lex.setup_ref_array(session, order_num) ||
1534
 
            setup_order(session, session->getLex()->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);
 
1554
        to->next_number_field->reset();
 
1555
    }
 
1556
 
 
1557
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
1558
    {
 
1559
      copy_ptr->do_copy(copy_ptr);
 
1560
    }
 
1561
    prev_insert_id= to->cursor->next_insert_id;
 
1562
    error= to->cursor->insertRecord(to->record[0]);
 
1563
    to->auto_increment_field_not_null= false;
 
1564
 
1550
1565
    if (error)
1551
 
    {
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)
 
1566
    { 
 
1567
      if (!ignore ||
 
1568
          to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1611
1569
      { 
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
 
      }
 
1570
        to->print_error(error, MYF(0));
 
1571
        break;
 
1572
      }
 
1573
      to->cursor->restore_auto_increment(prev_insert_id);
 
1574
      delete_count++;
1624
1575
    }
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)
 
1576
    else
1631
1577
    {
1632
 
      to->print_error(errno, MYF(0));
1633
 
      error= 1;
 
1578
      found_count++;
1634
1579
    }
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);
 
1580
  }
 
1581
 
 
1582
  info.end_read_record();
 
1583
  from->free_io_cache();
 
1584
  delete [] copy;                               // This is never 0
 
1585
 
 
1586
  if (to->cursor->ha_end_bulk_insert() && error <= 0)
 
1587
  {
 
1588
    to->print_error(errno, MYF(0));
 
1589
    error=1;
 
1590
  }
 
1591
  to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1592
 
 
1593
  /*
 
1594
    Ensure that the new table is saved properly to disk so that we
 
1595
    can do a rename
 
1596
  */
 
1597
  if (transaction_services.autocommitOrRollback(session, false))
 
1598
    error=1;
 
1599
  if (! session->endActiveTransaction())
 
1600
    error=1;
 
1601
 
 
1602
 err:
 
1603
  session->abort_on_warning= 0;
1650
1604
  from->free_io_cache();
1651
1605
  *copied= found_count;
1652
1606
  *deleted=delete_count;
1653
1607
  to->cursor->ha_release_auto_increment();
1654
 
 
1655
 
  if (to->cursor->ha_external_lock(session, F_UNLCK))
1656
 
  {
 
1608
  if (to->cursor->ha_external_lock(session,F_UNLCK))
1657
1609
    error=1;
1658
 
  }
1659
1610
 
1660
1611
  return(error > 0 ? -1 : 0);
1661
1612
}
1662
1613
 
1663
 
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
 
1614
static int
 
1615
create_temporary_table(Session *session,
 
1616
                       TableIdentifier &identifier,
 
1617
                       HA_CREATE_INFO *create_info,
 
1618
                       message::Table &create_proto,
 
1619
                       AlterInfo *alter_info)
 
1620
{
 
1621
  int error;
 
1622
 
 
1623
  /*
 
1624
    Create a table with a temporary name.
 
1625
    We don't log the statement, it will be logged later.
 
1626
  */
 
1627
  create_proto.set_name(identifier.getTableName());
 
1628
 
 
1629
  create_proto.mutable_engine()->set_name(create_info->db_type->getName());
 
1630
 
 
1631
  error= mysql_create_table(session,
 
1632
                            identifier,
 
1633
                            create_info, create_proto, alter_info, true, 0, false);
 
1634
 
 
1635
  return error;
 
1636
}
 
1637
 
 
1638
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
1664
1639
{
1665
1640
  Table *new_table;
1666
1641