~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: lbieber
  • Date: 2010-10-02 19:48:35 UTC
  • mfrom: (1730.6.19 drizzle-make-lcov)
  • Revision ID: lbieber@orisndriz08-20101002194835-q5zd9qc4lvx1xnfo
Merge Hartmut - clean up lex, now require flex to build, also "make lcov" improvements

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