~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: lbieber
  • Date: 2010-10-06 16:34:16 UTC
  • mfrom: (1816.1.3 build)
  • Revision ID: lbieber@orisndriz08-20101006163416-ea0sl59qgpglk21y
Merge Monty - Change the requirement from either libinnodb to libhaildb. Also, tied it to version 2.2
Merge Andrew - fix bug 650935: remove --compress from all clients
Merge Andrew - fix bug 653471: Add -A to drizzle client
Merge Travis - 621861 = To change C structs to C++ classes in Drizzle

Show diffs side-by-side

added added

removed removed

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