~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

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