~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Mark Atwood
  • Date: 2011-08-11 03:05:03 UTC
  • mfrom: (2385.1.12 refactor4)
  • Revision ID: me@mark.atwood.name-20110811030503-rp9xjihc5x3y0x4q
mergeĀ lp:~olafvdspek/drizzle/refactor4

Show diffs side-by-side

added added

removed removed

Lines of Context:
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"
 
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/charset.h>
 
32
#include <drizzled/gettext.h>
 
33
#include <drizzled/data_home.h>
 
34
#include <drizzled/sql_table.h>
 
35
#include <drizzled/table_proto.h>
 
36
#include <drizzled/optimizer/range.h>
 
37
#include <drizzled/time_functions.h>
 
38
#include <drizzled/records.h>
 
39
#include <drizzled/pthread_globals.h>
 
40
#include <drizzled/internal/my_sys.h>
 
41
#include <drizzled/internal/iocache.h>
 
42
#include <drizzled/plugin/storage_engine.h>
45
43
#include <drizzled/copy_field.h>
46
 
 
47
 
#include "drizzled/transaction_services.h"
48
 
 
49
 
#include "drizzled/filesort.h"
50
 
 
51
 
#include "drizzled/message.h"
 
44
#include <drizzled/transaction_services.h>
 
45
#include <drizzled/filesort.h>
 
46
#include <drizzled/message.h>
 
47
#include <drizzled/message/alter_table.pb.h>
 
48
#include <drizzled/alter_column.h>
 
49
#include <drizzled/alter_info.h>
 
50
#include <drizzled/util/test.h>
 
51
#include <drizzled/open_tables_state.h>
 
52
#include <drizzled/table/cache.h>
 
53
#include <drizzled/create_field.h>
52
54
 
53
55
using namespace std;
54
56
 
55
 
namespace drizzled
56
 
{
 
57
namespace drizzled {
57
58
 
58
59
extern pid_t current_pid;
59
60
 
65
66
                                    Order *order,
66
67
                                    ha_rows *copied,
67
68
                                    ha_rows *deleted,
68
 
                                    enum enum_enable_or_disable keys_onoff,
 
69
                                    message::AlterTable &alter_table_message,
69
70
                                    bool error_if_not_empty);
70
71
 
71
72
static bool prepare_alter_table(Session *session,
72
 
                                      Table *table,
73
 
                                      HA_CREATE_INFO *create_info,
74
 
                                      const message::Table &original_proto,
75
 
                                      message::Table &table_message,
76
 
                                      AlterInfo *alter_info);
 
73
                                Table *table,
 
74
                                HA_CREATE_INFO *create_info,
 
75
                                const message::Table &original_proto,
 
76
                                message::Table &table_message,
 
77
                                message::AlterTable &alter_table_message,
 
78
                                AlterInfo *alter_info);
77
79
 
78
80
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
79
81
 
 
82
static int apply_online_alter_keys_onoff(Session *session,
 
83
                                         Table* table,
 
84
                                         const message::AlterTable::AlterKeysOnOff &op);
 
85
 
 
86
static int apply_online_rename_table(Session *session,
 
87
                                     Table *table,
 
88
                                     plugin::StorageEngine *original_engine,
 
89
                                     identifier::Table &original_table_identifier,
 
90
                                     identifier::Table &new_table_identifier,
 
91
                                     const message::AlterTable::RenameTable &alter_operation);
 
92
 
80
93
namespace statement {
81
94
 
82
 
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
 
95
AlterTable::AlterTable(Session *in_session, Table_ident *) :
83
96
  CreateTable(in_session)
84
 
85
 
  in_session->lex->sql_command= SQLCOM_ALTER_TABLE;
86
 
  (void)ident;
87
 
  alter_info.build_method= build_arg;
 
97
{
 
98
  set_command(SQLCOM_ALTER_TABLE);
88
99
}
89
100
 
90
101
} // namespace statement
91
102
 
92
103
bool statement::AlterTable::execute()
93
104
{
94
 
  TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
95
 
  TableList *all_tables= getSession()->lex->query_tables;
 
105
  TableList *first_table= (TableList *) lex().select_lex.table_list.first;
 
106
  TableList *all_tables= lex().query_tables;
96
107
  assert(first_table == all_tables && first_table != 0);
97
 
  Select_Lex *select_lex= &getSession()->lex->select_lex;
98
 
  bool need_start_waiting= false;
 
108
  Select_Lex *select_lex= &lex().select_lex;
99
109
 
100
110
  is_engine_set= not createTableMessage().engine().name().empty();
101
111
 
102
112
  if (is_engine_set)
103
113
  {
104
 
    create_info().db_type= 
105
 
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
 
114
    create_info().db_type=
 
115
      plugin::StorageEngine::findByName(session(), createTableMessage().engine().name());
106
116
 
107
117
    if (create_info().db_type == NULL)
108
118
    {
119
129
  message::table::shared_ptr original_table_message;
120
130
  {
121
131
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
 
    if (plugin::StorageEngine::getTableDefinition(*getSession(), identifier, original_table_message) != EEXIST)
 
132
    if (not (original_table_message= plugin::StorageEngine::getTableMessage(session(), identifier)))
123
133
    {
124
134
      my_error(ER_BAD_TABLE_ERROR, identifier);
125
135
      return true;
127
137
 
128
138
    if (not  create_info().db_type)
129
139
    {
130
 
      create_info().db_type= 
131
 
        plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
 
140
      create_info().db_type=
 
141
        plugin::StorageEngine::findByName(session(), original_table_message->engine().name());
132
142
 
133
143
      if (not create_info().db_type)
134
144
      {
141
151
  if (not validateCreateTableOption())
142
152
    return true;
143
153
 
144
 
  if (getSession()->inTransaction())
 
154
  if (session().inTransaction())
145
155
  {
146
156
    my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
147
157
    return true;
148
158
  }
149
159
 
150
 
  if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
 
160
  if (session().wait_if_global_read_lock(0, 1))
151
161
    return true;
152
162
 
153
163
  bool res;
155
165
  {
156
166
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
167
    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());
 
168
                                   lex().name.str ? lex().name.str : first_table->getTableName());
159
169
 
160
 
    res= alter_table(getSession(), 
 
170
    res= alter_table(&session(),
161
171
                     identifier,
162
172
                     new_identifier,
163
173
                     &create_info(),
165
175
                     createTableMessage(),
166
176
                     first_table,
167
177
                     &alter_info,
168
 
                     select_lex->order_list.elements,
 
178
                     select_lex->order_list.size(),
169
179
                     (Order *) select_lex->order_list.first,
170
 
                     getSession()->lex->ignore);
 
180
                     lex().ignore);
171
181
  }
172
182
  else
173
183
  {
174
184
    identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
 
    Table *table= getSession()->find_temporary_table(catch22);
 
185
    Table *table= session().open_tables.find_temporary_table(catch22);
176
186
    assert(table);
177
187
    {
178
188
      identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
189
      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(),
 
190
                                       lex().name.str ? lex().name.str : first_table->getTableName(),
181
191
                                       table->getMutableShare()->getPath());
182
192
 
183
 
      res= alter_table(getSession(), 
 
193
      res= alter_table(&session(),
184
194
                       identifier,
185
195
                       new_identifier,
186
196
                       &create_info(),
188
198
                       createTableMessage(),
189
199
                       first_table,
190
200
                       &alter_info,
191
 
                       select_lex->order_list.elements,
 
201
                       select_lex->order_list.size(),
192
202
                       (Order *) select_lex->order_list.first,
193
 
                       getSession()->lex->ignore);
 
203
                       lex().ignore);
194
204
    }
195
205
  }
196
206
 
198
208
     Release the protection against the global read lock and wake
199
209
     everyone, who might want to set a global read lock.
200
210
   */
201
 
  getSession()->startWaitingGlobalReadLock();
 
211
  session().startWaitingGlobalReadLock();
202
212
 
203
213
  return res;
204
214
}
249
259
                                HA_CREATE_INFO *create_info,
250
260
                                const message::Table &original_proto,
251
261
                                message::Table &table_message,
 
262
                                message::AlterTable &alter_table_message,
252
263
                                AlterInfo *alter_info)
253
264
{
254
 
  /* New column definitions are added here */
255
 
  List<CreateField> new_create_list;
256
 
  /* New key definitions are added here */
257
 
  List<Key> new_key_list;
258
 
  List_iterator<AlterDrop> drop_it(alter_info->drop_list);
259
 
  List_iterator<CreateField> def_it(alter_info->create_list);
260
 
  List_iterator<AlterColumn> alter_it(alter_info->alter_list);
261
 
  List_iterator<Key> key_it(alter_info->key_list);
262
 
  List_iterator<CreateField> find_it(new_create_list);
263
 
  List_iterator<CreateField> field_it(new_create_list);
264
 
  List<Key_part_spec> key_parts;
265
265
  uint32_t used_fields= create_info->used_fields;
266
 
  KeyInfo *key_info= table->key_info;
267
 
  bool rc= true;
 
266
  vector<string> drop_keys;
 
267
  vector<string> drop_columns;
 
268
  vector<string> drop_fkeys;
 
269
 
 
270
  /* we use drop_(keys|columns|fkey) below to check that we can do all
 
271
     operations we've been asked to do */
 
272
  for (int operationnr= 0; operationnr < alter_table_message.operations_size();
 
273
       operationnr++)
 
274
  {
 
275
    const message::AlterTable::AlterTableOperation &operation=
 
276
      alter_table_message.operations(operationnr);
 
277
 
 
278
    switch (operation.operation())
 
279
    {
 
280
    case message::AlterTable::AlterTableOperation::DROP_KEY:
 
281
      drop_keys.push_back(operation.drop_name());
 
282
      break;
 
283
    case message::AlterTable::AlterTableOperation::DROP_COLUMN:
 
284
      drop_columns.push_back(operation.drop_name());
 
285
      break;
 
286
    case message::AlterTable::AlterTableOperation::DROP_FOREIGN_KEY:
 
287
      drop_fkeys.push_back(operation.drop_name());
 
288
      break;
 
289
    default:
 
290
      break;
 
291
    }
 
292
  }
268
293
 
269
294
  /* Let new create options override the old ones */
270
 
  message::Table::TableOptions *table_options;
271
 
  table_options= table_message.mutable_options();
 
295
  message::Table::TableOptions *table_options= table_message.mutable_options();
272
296
 
273
297
  if (not (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
274
298
    create_info->default_table_charset= table->getShare()->table_charset;
283
307
  }
284
308
 
285
309
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
286
 
  CreateField *def;
287
310
 
 
311
  List<CreateField> new_create_list;
 
312
  List<Key> new_key_list;
288
313
  /* First collect all fields from table which isn't in drop_list */
289
314
  Field *field;
290
315
  for (Field **f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
291
316
  {
292
317
    /* Check if field should be dropped */
293
 
    AlterDrop *drop;
294
 
    drop_it.rewind();
295
 
    while ((drop= drop_it++))
 
318
    vector<string>::iterator it= drop_columns.begin();
 
319
    while ((it != drop_columns.end()))
296
320
    {
297
 
      if (drop->type == AlterDrop::COLUMN &&
298
 
          ! my_strcasecmp(system_charset_info, field->field_name, drop->name))
 
321
      if (! my_strcasecmp(system_charset_info, field->field_name, (*it).c_str()))
299
322
      {
300
323
        /* Reset auto_increment value if it was dropped */
301
324
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
302
 
            ! (used_fields & HA_CREATE_USED_AUTO))
 
325
            not (used_fields & HA_CREATE_USED_AUTO))
303
326
        {
304
327
          create_info->auto_increment_value= 0;
305
328
          create_info->used_fields|= HA_CREATE_USED_AUTO;
306
329
        }
307
330
        break;
308
331
      }
 
332
      it++;
309
333
    }
310
334
 
311
 
    if (drop)
 
335
    if (it != drop_columns.end())
312
336
    {
313
 
      drop_it.remove();
 
337
      drop_columns.erase(it);
314
338
      continue;
315
339
    }
316
 
    
 
340
 
317
341
    /* Mark that we will read the field */
318
342
    field->setReadSet();
319
343
 
 
344
    CreateField *def;
320
345
    /* Check if field is changed */
321
 
    def_it.rewind();
 
346
    List<CreateField>::iterator def_it= alter_info->create_list.begin();
322
347
    while ((def= def_it++))
323
348
    {
324
349
      if (def->change &&
344
369
      */
345
370
      def= new CreateField(field, field);
346
371
      new_create_list.push_back(def);
347
 
      alter_it.rewind(); /* Change default if ALTER */
348
 
      AlterColumn *alter;
 
372
      AlterInfo::alter_list_t::iterator alter(alter_info->alter_list.begin());
349
373
 
350
 
      while ((alter= alter_it++))
 
374
      for (; alter != alter_info->alter_list.end(); alter++)
351
375
      {
352
 
        if (! my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
376
        if (not my_strcasecmp(system_charset_info,field->field_name, alter->name))
353
377
          break;
354
378
      }
355
379
 
356
 
      if (alter)
 
380
      if (alter != alter_info->alter_list.end())
357
381
      {
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
 
        }
 
382
        def->setDefaultValue(alter->def, NULL);
363
383
 
364
 
        if ((def->def= alter->def))
365
 
        {
366
 
          /* Use new default */
367
 
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
368
 
        }
369
 
        else
370
 
        {
371
 
          def->flags|= NO_DEFAULT_VALUE_FLAG;
372
 
        }
373
 
        alter_it.remove();
 
384
        alter_info->alter_list.erase(alter);
374
385
      }
375
386
    }
376
387
  }
377
388
 
378
 
  def_it.rewind();
 
389
  CreateField *def;
 
390
  List<CreateField>::iterator def_it= alter_info->create_list.begin();
379
391
  while ((def= def_it++)) /* Add new columns */
380
392
  {
381
393
    if (def->change && ! def->field)
401
413
    else
402
414
    {
403
415
      CreateField *find;
404
 
      find_it.rewind();
 
416
      List<CreateField>::iterator find_it= new_create_list.begin();
405
417
 
406
418
      while ((find= find_it++)) /* Add new columns */
407
419
      {
427
439
        TODO: detect the situation in compare_tables, behave based
428
440
        on engine capabilities.
429
441
      */
430
 
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
442
      if (alter_table_message.build_method() == message::AlterTable::BUILD_ONLINE)
431
443
      {
432
444
        my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
433
445
        return true;
434
446
      }
435
 
 
436
 
      alter_info->build_method= HA_BUILD_OFFLINE;
437
447
    }
438
448
  }
439
449
 
440
 
  if (alter_info->alter_list.elements)
 
450
  if (not alter_info->alter_list.empty())
441
451
  {
442
 
    my_error(ER_BAD_FIELD_ERROR,
443
 
             MYF(0),
444
 
             alter_info->alter_list.head()->name,
445
 
             table->getMutableShare()->getTableName());
 
452
    my_error(ER_BAD_FIELD_ERROR, MYF(0), alter_info->alter_list.front().name, table->getMutableShare()->getTableName());
446
453
    return true;
447
454
  }
448
455
 
449
 
  if (not new_create_list.elements)
 
456
  if (new_create_list.is_empty())
450
457
  {
451
 
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
 
               ER(ER_CANT_REMOVE_ALL_FIELDS),
453
 
               MYF(0));
 
458
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS), MYF(0));
454
459
    return true;
455
460
  }
456
461
 
458
463
    Collect all keys which isn't in drop list. Add only those
459
464
    for which some fields exists.
460
465
  */
 
466
  KeyInfo *key_info= table->key_info;
461
467
  for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
462
468
  {
463
469
    char *key_name= key_info->name;
464
 
    AlterDrop *drop;
465
470
 
466
 
    drop_it.rewind();
467
 
    while ((drop= drop_it++))
 
471
    vector<string>::iterator it= drop_keys.begin();
 
472
    while ((it != drop_keys.end()))
468
473
    {
469
 
      if (drop->type == AlterDrop::KEY &&
470
 
          ! my_strcasecmp(system_charset_info, key_name, drop->name))
 
474
      if (! my_strcasecmp(system_charset_info, key_name, (*it).c_str()))
471
475
        break;
 
476
      it++;
472
477
    }
473
478
 
474
 
    if (drop)
 
479
    if (it != drop_keys.end())
475
480
    {
476
 
      drop_it.remove();
 
481
      drop_keys.erase(it);
477
482
      continue;
478
483
    }
479
484
 
480
485
    KeyPartInfo *key_part= key_info->key_part;
481
 
    key_parts.empty();
 
486
    List<Key_part_spec> key_parts;
482
487
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
483
488
    {
484
489
      if (! key_part->field)
486
491
 
487
492
      const char *key_part_name= key_part->field->field_name;
488
493
      CreateField *cfield;
489
 
      field_it.rewind();
 
494
      List<CreateField>::iterator field_it= new_create_list.begin();
490
495
      while ((cfield= field_it++))
491
496
      {
492
497
        if (cfield->change)
500
505
 
501
506
      if (not cfield)
502
507
              continue; /* Field is removed */
503
 
      
 
508
 
504
509
      uint32_t key_part_length= key_part->length;
505
510
      if (cfield->field) /* Not new field */
506
511
      {
528
533
                                            strlen(cfield->field_name),
529
534
                                            key_part_length));
530
535
    }
531
 
    if (key_parts.elements)
 
536
    if (key_parts.size())
532
537
    {
533
538
      key_create_information_st key_create_info= default_key_create_info;
534
539
      Key *key;
567
572
  /* Copy over existing foreign keys */
568
573
  for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
569
574
  {
570
 
    AlterDrop *drop;
571
 
    drop_it.rewind();
572
 
    while ((drop= drop_it++))
 
575
    vector<string>::iterator it= drop_fkeys.begin();
 
576
    while ((it != drop_fkeys.end()))
573
577
    {
574
 
      if (drop->type == AlterDrop::FOREIGN_KEY &&
575
 
          ! my_strcasecmp(system_charset_info, original_proto.fk_constraint(j).name().c_str(), drop->name))
 
578
      if (! my_strcasecmp(system_charset_info, original_proto.fk_constraint(j).name().c_str(), (*it).c_str()))
576
579
      {
577
580
        break;
578
581
      }
 
582
      it++;
579
583
    }
580
 
    if (drop)
 
584
 
 
585
    if (it != drop_fkeys.end())
581
586
    {
582
 
      drop_it.remove();
 
587
      drop_fkeys.erase(it);
583
588
      continue;
584
589
    }
585
590
 
589
594
 
590
595
  {
591
596
    Key *key;
 
597
    List<Key>::iterator key_it(alter_info->key_list.begin());
592
598
    while ((key= key_it++)) /* Add new keys */
593
599
    {
594
600
      if (key->type == Key::FOREIGN_KEY)
639
645
    }
640
646
  }
641
647
 
642
 
  if (alter_info->drop_list.elements)
643
 
  {
644
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
645
 
             MYF(0),
646
 
             alter_info->drop_list.head()->name);
647
 
    return true;
648
 
  }
649
 
 
650
 
  if (alter_info->alter_list.elements)
651
 
  {
652
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
653
 
             MYF(0),
654
 
             alter_info->alter_list.head()->name);
 
648
  if (drop_keys.size())
 
649
  {
 
650
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
 
651
             MYF(0),
 
652
             drop_keys.front().c_str());
 
653
    return true;
 
654
  }
 
655
 
 
656
  if (drop_columns.size())
 
657
  {
 
658
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
 
659
             MYF(0),
 
660
             drop_columns.front().c_str());
 
661
    return true;
 
662
  }
 
663
 
 
664
  if (drop_fkeys.size())
 
665
  {
 
666
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
 
667
             MYF(0),
 
668
             drop_fkeys.front().c_str());
 
669
    return true;
 
670
  }
 
671
 
 
672
  if (not alter_info->alter_list.empty())
 
673
  {
 
674
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
 
675
             MYF(0),
 
676
             alter_info->alter_list.front().name);
655
677
    return true;
656
678
  }
657
679
 
670
692
  table_message.set_version(table->getShare()->getTableMessage()->version());
671
693
  table_message.set_uuid(table->getShare()->getTableMessage()->uuid());
672
694
 
673
 
  rc= false;
674
695
  alter_info->create_list.swap(new_create_list);
675
696
  alter_info->key_list.swap(new_key_list);
676
697
 
683
704
    for (size_t y= 0; y < num_engine_options; ++y)
684
705
    {
685
706
      found= not table_message.engine().options(y).name().compare(original_proto.engine().options(x).name());
686
 
      
 
707
 
687
708
      if (found)
688
709
        break;
689
710
    }
704
725
 
705
726
/* table_list should contain just one table */
706
727
static int discard_or_import_tablespace(Session *session,
707
 
                                              TableList *table_list,
708
 
                                              enum tablespace_op_type tablespace_op)
 
728
                                        TableList *table_list,
 
729
                                        bool discard)
709
730
{
710
 
  Table *table;
711
 
  bool discard;
712
 
 
713
731
  /*
714
732
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
715
733
    ALTER Table
716
734
  */
717
 
  TransactionServices &transaction_services= TransactionServices::singleton();
718
735
  session->set_proc_info("discard_or_import_tablespace");
719
736
 
720
 
  discard= test(tablespace_op == DISCARD_TABLESPACE);
721
 
 
722
737
 /*
723
738
   We set this flag so that ha_innobase::open and ::external_lock() do
724
739
   not complain when we lock the table
725
740
 */
726
741
  session->setDoingTablespaceOperation(true);
727
 
  if (not (table= session->openTableLock(table_list, TL_WRITE)))
 
742
  Table* table= session->openTableLock(table_list, TL_WRITE);
 
743
  if (not table)
728
744
  {
729
745
    session->setDoingTablespaceOperation(false);
730
746
    return -1;
740
756
      break;
741
757
 
742
758
    /* The ALTER Table is always in its own transaction */
743
 
    error= transaction_services.autocommitOrRollback(*session, false);
 
759
    error= TransactionServices::autocommitOrRollback(*session, false);
744
760
    if (not session->endActiveTransaction())
745
761
      error= 1;
746
762
 
747
763
    if (error)
748
764
      break;
749
765
 
750
 
    write_bin_log(session, *session->getQueryString());
 
766
    TransactionServices::rawStatement(*session,
 
767
                                      *session->getQueryString(),
 
768
                                      *session->schema());
751
769
 
752
770
  } while(0);
753
771
 
754
 
  (void) transaction_services.autocommitOrRollback(*session, error);
 
772
  (void) TransactionServices::autocommitOrRollback(*session, error);
755
773
  session->setDoingTablespaceOperation(false);
756
774
 
757
775
  if (error == 0)
781
799
*/
782
800
static bool alter_table_manage_keys(Session *session,
783
801
                                    Table *table, int indexes_were_disabled,
784
 
                                    enum enum_enable_or_disable keys_onoff)
 
802
                                    const message::AlterTable &alter_table_message)
785
803
{
786
804
  int error= 0;
787
 
  switch (keys_onoff) {
788
 
  case ENABLE:
 
805
  if (alter_table_message.has_alter_keys_onoff()
 
806
      && alter_table_message.alter_keys_onoff().enable())
 
807
  {
789
808
    error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
790
 
    break;
791
 
  case LEAVE_AS_IS:
792
 
    if (not indexes_were_disabled)
793
 
      break;
794
 
    /* fall-through: disabled indexes */
795
 
  case DISABLE:
 
809
  }
 
810
 
 
811
  if ((! alter_table_message.has_alter_keys_onoff() && indexes_were_disabled)
 
812
      || (alter_table_message.has_alter_keys_onoff()
 
813
          && ! alter_table_message.alter_keys_onoff().enable()))
 
814
  {
796
815
    error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
797
816
  }
798
817
 
821
840
  {
822
841
    if (original_table_identifier.isTmp())
823
842
    {
824
 
 
825
 
      if (session.find_temporary_table(new_table_identifier))
 
843
      if (session.open_tables.find_temporary_table(new_table_identifier))
826
844
      {
827
845
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
828
846
        return false;
830
848
    }
831
849
    else
832
850
    {
833
 
      if (session.lock_table_name_if_not_cached(new_table_identifier, &name_lock))
834
 
      {
835
 
        return false;
836
 
      }
837
 
 
 
851
      name_lock= session.lock_table_name_if_not_cached(new_table_identifier);
838
852
      if (not name_lock)
839
853
      {
840
854
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
847
861
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
848
862
 
849
863
        {
850
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
864
          boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
851
865
          session.unlink_open_table(name_lock);
852
866
        }
853
867
 
908
922
                                 HA_CREATE_INFO *create_info,
909
923
                                 const message::Table &original_proto,
910
924
                                 message::Table &create_proto,
 
925
                                 message::AlterTable &alter_table_message,
911
926
                                 TableList *table_list,
912
927
                                 AlterInfo *alter_info,
913
928
                                 uint32_t order_num,
946
961
  create_proto.set_type(new_table_identifier.getType());
947
962
 
948
963
  /**
949
 
    @todo Have a check on the table definition for FK in the future 
 
964
    @todo Have a check on the table definition for FK in the future
950
965
    to remove the need for the cursor. (aka can_switch_engines())
951
966
  */
952
967
  if (new_engine != original_engine &&
968
983
 
969
984
  session->set_proc_info("setup");
970
985
 
971
 
  /*
972
 
   * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
973
 
 */
 
986
  /* First we try for operations that do not require a copying
 
987
     ALTER TABLE.
 
988
 
 
989
     In future there should be more operations, currently it's just a couple.
 
990
  */
 
991
 
 
992
  if ((alter_table_message.has_rename()
 
993
       || alter_table_message.has_alter_keys_onoff())
 
994
      && alter_table_message.operations_size() == 0)
974
995
  {
 
996
    /*
 
997
     * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
 
998
     */
975
999
    bitset<32> tmp;
976
1000
 
977
1001
    tmp.set();
979
1003
    tmp.reset(ALTER_KEYS_ONOFF);
980
1004
    tmp&= alter_info->flags;
981
1005
 
982
 
    if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
 
1006
    if((not (tmp.any()) && not table->getShare()->getType())) // no need to touch frm
983
1007
    {
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);
1056
 
          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());
 
1008
      if (alter_table_message.has_alter_keys_onoff())
 
1009
      {
 
1010
        error= apply_online_alter_keys_onoff(session, table,
 
1011
                                       alter_table_message.alter_keys_onoff());
 
1012
 
 
1013
        if (error == HA_ERR_WRONG_COMMAND)
 
1014
        {
 
1015
          error= EE_OK;
 
1016
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1017
                              ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
1018
                              table->getAlias());
 
1019
        }
 
1020
      }
 
1021
 
 
1022
      if (alter_table_message.has_rename())
 
1023
      {
 
1024
        error= apply_online_rename_table(session,
 
1025
                                         table,
 
1026
                                         original_engine,
 
1027
                                         original_table_identifier,
 
1028
                                         new_table_identifier,
 
1029
                                         alter_table_message.rename());
 
1030
 
 
1031
        if (error == HA_ERR_WRONG_COMMAND)
 
1032
        {
 
1033
          error= EE_OK;
 
1034
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1035
                              ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
1036
                              table->getAlias());
 
1037
        }
1073
1038
      }
1074
1039
 
1075
1040
      if (not error)
1076
1041
      {
1077
 
        TransactionServices &transaction_services= TransactionServices::singleton();
1078
 
        transaction_services.allocateNewTransactionId();
1079
 
        write_bin_log(session, *session->getQueryString());
 
1042
        TransactionServices::allocateNewTransactionId();
 
1043
        TransactionServices::rawStatement(*session,
 
1044
                                          *session->getQueryString(),
 
1045
                                          *session->schema());
1080
1046
        session->my_ok();
1081
1047
      }
1082
1048
      else if (error > EE_OK) // If we have already set the error, we pass along -1
1090
1056
    }
1091
1057
  }
1092
1058
 
 
1059
  if (alter_table_message.build_method() == message::AlterTable::BUILD_ONLINE)
 
1060
  {
 
1061
    my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
 
1062
    return true;
 
1063
  }
 
1064
 
1093
1065
  /* We have to do full alter table. */
1094
1066
  new_engine= create_info->db_type;
1095
1067
 
1096
 
  if (prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
 
1068
  if (prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_table_message, alter_info))
1097
1069
  {
1098
1070
    return true;
1099
1071
  }
1100
1072
 
1101
1073
  set_table_default_charset(create_info, new_table_identifier.getSchemaName().c_str());
1102
1074
 
1103
 
  alter_info->build_method= HA_BUILD_OFFLINE;
1104
 
 
1105
1075
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1106
1076
 
1107
1077
  /* Create a temporary table with the new format */
1161
1131
                                    order,
1162
1132
                                    &copied,
1163
1133
                                    &deleted,
1164
 
                                    alter_info->keys_onoff,
 
1134
                                    alter_table_message,
1165
1135
                                    alter_info->error_if_not_empty);
1166
1136
 
1167
1137
    /* We must not ignore bad input! */
1186
1156
      if (new_table)
1187
1157
      {
1188
1158
        /* close_temporary_table() frees the new_table pointer. */
1189
 
        session->close_temporary_table(new_table);
 
1159
        session->open_tables.close_temporary_table(new_table);
1190
1160
      }
1191
1161
      else
1192
1162
      {
1212
1182
        delete new_table;
1213
1183
      }
1214
1184
 
1215
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1185
      boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
1216
1186
 
1217
1187
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1218
1188
 
1223
1193
  else if (original_table_identifier.isTmp())
1224
1194
  {
1225
1195
    /* Close lock if this is a transactional table */
1226
 
    if (session->lock)
 
1196
    if (session->open_tables.lock)
1227
1197
    {
1228
 
      session->unlockTables(session->lock);
1229
 
      session->lock= 0;
 
1198
      session->unlockTables(session->open_tables.lock);
 
1199
      session->open_tables.lock= 0;
1230
1200
    }
1231
1201
 
1232
1202
    /* Remove link to old table and rename the new one */
1233
 
    session->close_temporary_table(table);
 
1203
    session->open_tables.close_temporary_table(table);
1234
1204
 
1235
1205
    /* Should pass the 'new_name' as we store table name in the cache */
1236
1206
    new_table->getMutableShare()->setIdentifier(new_table_identifier);
1262
1232
    }
1263
1233
 
1264
1234
    {
1265
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* ALTER TABLE */
 
1235
      boost::mutex::scoped_lock scopedLock(table::Cache::mutex()); /* ALTER TABLE */
1266
1236
      /*
1267
1237
        Data is copied. Now we:
1268
1238
        1) Wait until all other threads close old version of table.
1343
1313
 
1344
1314
    session->set_proc_info("end");
1345
1315
 
1346
 
    write_bin_log(session, *session->getQueryString());
 
1316
    TransactionServices::rawStatement(*session,
 
1317
                                      *session->getQueryString(),
 
1318
                                      *session->schema());
1347
1319
    table_list->table= NULL;
1348
1320
  }
1349
1321
 
1350
1322
  /*
1351
 
   * Field::store() may have called my_error().  If this is 
1352
 
   * the case, we must not send an ok packet, since 
 
1323
   * Field::store() may have called my_error().  If this is
 
1324
   * the case, we must not send an ok packet, since
1353
1325
   * Diagnostics_area::is_set() will fail an assert.
1354
1326
 */
1355
1327
  if (session->is_error())
1362
1334
           (ulong) (copied + deleted), (ulong) deleted,
1363
1335
           (ulong) session->cuted_fields);
1364
1336
  session->my_ok(copied + deleted, 0, 0L, tmp_name);
1365
 
  session->some_tables_deleted= false;
1366
 
 
1367
1337
  return false;
1368
1338
}
1369
1339
 
 
1340
static int apply_online_alter_keys_onoff(Session *session,
 
1341
                                         Table* table,
 
1342
                                         const message::AlterTable::AlterKeysOnOff &op)
 
1343
{
 
1344
  int error= 0;
 
1345
 
 
1346
  if (op.enable())
 
1347
  {
 
1348
    /*
 
1349
      wait_while_table_is_used() ensures that table being altered is
 
1350
      opened only by this thread and that Table::TableShare::version
 
1351
      of Table object corresponding to this table is 0.
 
1352
      The latter guarantees that no DML statement will open this table
 
1353
      until ALTER Table finishes (i.e. until close_thread_tables())
 
1354
      while the fact that the table is still open gives us protection
 
1355
      from concurrent DDL statements.
 
1356
    */
 
1357
    {
 
1358
      boost::mutex::scoped_lock scopedLock(table::Cache::mutex()); /* DDL wait for/blocker */
 
1359
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
1360
    }
 
1361
    error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
1362
 
 
1363
    /* COND_refresh will be signaled in close_thread_tables() */
 
1364
  }
 
1365
  else
 
1366
  {
 
1367
    {
 
1368
      boost::mutex::scoped_lock scopedLock(table::Cache::mutex()); /* DDL wait for/blocker */
 
1369
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
1370
    }
 
1371
    error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
1372
 
 
1373
    /* COND_refresh will be signaled in close_thread_tables() */
 
1374
  }
 
1375
 
 
1376
  return error;
 
1377
}
 
1378
 
 
1379
static int apply_online_rename_table(Session *session,
 
1380
                                     Table *table,
 
1381
                                     plugin::StorageEngine *original_engine,
 
1382
                                     identifier::Table &original_table_identifier,
 
1383
                                     identifier::Table &new_table_identifier,
 
1384
                                     const message::AlterTable::RenameTable &alter_operation)
 
1385
{
 
1386
  int error= 0;
 
1387
 
 
1388
  boost::mutex::scoped_lock scopedLock(table::Cache::mutex()); /* Lock to remove all instances of table from table cache before ALTER */
 
1389
  /*
 
1390
    Unlike to the above case close_cached_table() below will remove ALL
 
1391
    instances of Table from table cache (it will also remove table lock
 
1392
    held by this thread). So to make actual table renaming and writing
 
1393
    to binlog atomic we have to put them into the same critical section
 
1394
    protected by table::Cache::mutex() mutex. This also removes gap for races between
 
1395
    access() and rename_table() calls.
 
1396
  */
 
1397
 
 
1398
  if (not (original_table_identifier == new_table_identifier))
 
1399
  {
 
1400
    assert(alter_operation.to_name() == new_table_identifier.getTableName());
 
1401
    assert(alter_operation.to_schema() == new_table_identifier.getSchemaName());
 
1402
 
 
1403
    session->set_proc_info("rename");
 
1404
    /*
 
1405
      Then do a 'simple' rename of the table. First we need to close all
 
1406
      instances of 'source' table.
 
1407
    */
 
1408
    session->close_cached_table(table);
 
1409
    /*
 
1410
      Then, we want check once again that target table does not exist.
 
1411
      Actually the order of these two steps does not matter since
 
1412
      earlier we took name-lock on the target table, so we do them
 
1413
      in this particular order only to be consistent with 5.0, in which
 
1414
      we don't take this name-lock and where this order really matters.
 
1415
      @todo Investigate if we need this access() check at all.
 
1416
    */
 
1417
    if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
 
1418
    {
 
1419
      my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
1420
      error= -1;
 
1421
    }
 
1422
    else
 
1423
    {
 
1424
      if (rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
 
1425
      {
 
1426
        error= -1;
 
1427
      }
 
1428
    }
 
1429
  }
 
1430
  return error;
 
1431
}
 
1432
 
1370
1433
bool alter_table(Session *session,
1371
1434
                 identifier::Table &original_table_identifier,
1372
1435
                 identifier::Table &new_table_identifier,
1381
1444
{
1382
1445
  bool error;
1383
1446
  Table *table;
1384
 
 
1385
 
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
1447
  message::AlterTable *alter_table_message= session->lex().alter_table();
 
1448
 
 
1449
  alter_table_message->set_catalog(original_table_identifier.getCatalogName());
 
1450
  alter_table_message->set_schema(original_table_identifier.getSchemaName());
 
1451
  alter_table_message->set_name(original_table_identifier.getTableName());
 
1452
 
 
1453
  if (alter_table_message->operations_size()
 
1454
      && (alter_table_message->operations(0).operation()
 
1455
          == message::AlterTable::AlterTableOperation::DISCARD_TABLESPACE
 
1456
          || alter_table_message->operations(0).operation()
 
1457
          == message::AlterTable::AlterTableOperation::IMPORT_TABLESPACE))
1386
1458
  {
 
1459
    bool discard= (alter_table_message->operations(0).operation() ==
 
1460
                   message::AlterTable::AlterTableOperation::DISCARD_TABLESPACE);
1387
1461
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
1388
 
    return discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
 
1462
    return discard_or_import_tablespace(session, table_list, discard);
1389
1463
  }
1390
1464
 
1391
1465
  session->set_proc_info("init");
1395
1469
 
1396
1470
  session->set_proc_info("gained write lock on table");
1397
1471
 
1398
 
  /* 
 
1472
  /*
1399
1473
    Check that we are not trying to rename to an existing table,
1400
1474
    if one existed we get a lock, if we can't we error.
1401
1475
  */
1414
1488
                                create_info,
1415
1489
                                original_proto,
1416
1490
                                create_proto,
 
1491
                                *alter_table_message,
1417
1492
                                table_list,
1418
1493
                                alter_info,
1419
1494
                                order_num,
1422
1497
 
1423
1498
    if (name_lock)
1424
1499
    {
1425
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1500
      boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
1426
1501
      session->unlink_open_table(name_lock);
1427
1502
    }
1428
1503
  }
1439
1514
                         uint32_t order_num, Order *order,
1440
1515
                         ha_rows *copied,
1441
1516
                         ha_rows *deleted,
1442
 
                         enum enum_enable_or_disable keys_onoff,
 
1517
                         message::AlterTable &alter_table_message,
1443
1518
                         bool error_if_not_empty)
1444
1519
{
1445
1520
  int error= 0;
1461
1536
 
1462
1537
    This needs to be done before external_lock
1463
1538
  */
1464
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1465
1539
 
1466
 
  /* 
1467
 
   * LP Bug #552420 
 
1540
  /*
 
1541
   * LP Bug #552420
1468
1542
   *
1469
1543
   * Since open_temporary_table() doesn't invoke lockTables(), we
1470
1544
   * don't get the usual automatic call to StorageEngine::startStatement(), so
1472
1546
   */
1473
1547
  to->getMutableShare()->getEngine()->startStatement(session);
1474
1548
 
1475
 
  if (!(copy= new CopyField[to->getShare()->sizeFields()]))
1476
 
    return -1;
 
1549
  copy= new CopyField[to->getShare()->sizeFields()];
1477
1550
 
1478
1551
  if (to->cursor->ha_external_lock(session, F_WRLCK))
1479
1552
    return -1;
1480
1553
 
1481
1554
  /* We need external lock before we can disable/enable keys */
1482
 
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
 
1555
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(),
 
1556
                          alter_table_message);
1483
1557
 
1484
1558
  /* We can abort alter table for any table type */
1485
1559
  session->setAbortOnWarning(not ignore);
1487
1561
  from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
1562
  to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
1489
1563
 
1490
 
  List_iterator<CreateField> it(create);
1491
 
  CreateField *def;
 
1564
  List<CreateField>::iterator it(create.begin());
1492
1565
  copy_end= copy;
1493
1566
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
1494
1567
  {
1495
 
    def=it++;
 
1568
    CreateField* def=it++;
1496
1569
    if (def->field)
1497
1570
    {
1498
1571
      if (*ptr == to->next_number_field)
1522
1595
      else
1523
1596
      {
1524
1597
        FileSort filesort(*session);
1525
 
        from->sort.io_cache= new internal::IO_CACHE;
 
1598
        from->sort.io_cache= new internal::io_cache_st;
1526
1599
 
1527
1600
        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()));
 
1601
        tables.setTableName(from->getMutableShare()->getTableName());
 
1602
        tables.alias= tables.getTableName();
 
1603
        tables.setSchemaName(from->getMutableShare()->getSchemaName());
1531
1604
        error= 1;
1532
1605
 
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
 
        }
 
1606
        session->lex().select_lex.setup_ref_array(session, order_num);
 
1607
        if (setup_order(session, session->lex().select_lex.ref_pointer_array, &tables, fields, all_fields, order))
 
1608
          break;
 
1609
        sortorder= make_unireg_sortorder(order, &length, NULL);
 
1610
        if ((from->sort.found_records= filesort.run(from, sortorder, length, (optimizer::SqlSelect *) 0, HA_POS_ERROR, 1, examined_rows)) == HA_POS_ERROR)
 
1611
          break;
1543
1612
      }
1544
1613
    }
1545
1614
 
1546
1615
    /* Tell handler that we have values for all columns in the to table */
1547
1616
    to->use_all_columns();
1548
1617
 
1549
 
    error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
 
1618
    error= info.init_read_record(session, from, NULL, 1, true);
1550
1619
    if (error)
1551
1620
    {
1552
1621
      to->print_error(errno, MYF(0));
1608
1677
      to->auto_increment_field_not_null= false;
1609
1678
 
1610
1679
      if (error)
1611
 
      { 
 
1680
      {
1612
1681
        if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1613
 
        { 
 
1682
        {
1614
1683
          to->print_error(error, MYF(0));
1615
1684
          break;
1616
1685
        }
1625
1694
 
1626
1695
    info.end_read_record();
1627
1696
    from->free_io_cache();
1628
 
    delete [] copy;                             // This is never 0
 
1697
    delete[] copy;
1629
1698
 
1630
1699
    if (to->cursor->ha_end_bulk_insert() && error <= 0)
1631
1700
    {
1638
1707
      Ensure that the new table is saved properly to disk so that we
1639
1708
      can do a rename
1640
1709
    */
1641
 
    if (transaction_services.autocommitOrRollback(*session, false))
 
1710
    if (TransactionServices::autocommitOrRollback(*session, false))
1642
1711
      error= 1;
1643
1712
 
1644
1713
    if (not session->endActiveTransaction())
1654
1723
 
1655
1724
  if (to->cursor->ha_external_lock(session, F_UNLCK))
1656
1725
  {
1657
 
    error=1;
 
1726
    error= 1;
1658
1727
  }
1659
1728
 
1660
 
  return(error > 0 ? -1 : 0);
 
1729
  return error > 0 ? -1 : 0;
1661
1730
}
1662
1731
 
1663
1732
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
1664
1733
{
1665
 
  Table *new_table;
1666
 
 
1667
1734
  /* Open the table so we need to copy the data to it. */
1668
1735
  if (table->getShare()->getType())
1669
1736
  {
1670
1737
    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()));
 
1738
    tbl.setSchemaName(identifier.getSchemaName().c_str());
 
1739
    tbl.alias= identifier.getTableName().c_str();
 
1740
    tbl.setTableName(identifier.getTableName().c_str());
1674
1741
 
1675
1742
    /* Table is in session->temporary_tables */
1676
 
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1743
    return session->openTable(&tbl, NULL, DRIZZLE_LOCK_IGNORE_FLUSH);
1677
1744
  }
1678
1745
  else
1679
1746
  {
1680
1747
    /* Open our intermediate table */
1681
 
    new_table= session->open_temporary_table(identifier, false);
 
1748
    return session->open_temporary_table(identifier, false);
1682
1749
  }
1683
 
 
1684
 
  return new_table;
1685
1750
}
1686
1751
 
1687
1752
} /* namespace drizzled */