~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

edit

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include <config.h>
 
21
#include "config.h"
22
22
 
23
23
#include <fcntl.h>
24
24
 
25
25
#include <sstream>
26
26
 
27
 
#include <drizzled/show.h>
28
 
#include <drizzled/lock.h>
29
 
#include <drizzled/session.h>
30
 
#include <drizzled/statement/alter_table.h>
31
 
#include <drizzled/global_charset_info.h>
32
 
 
33
 
 
34
 
#include <drizzled/gettext.h>
35
 
#include <drizzled/data_home.h>
36
 
#include <drizzled/sql_table.h>
37
 
#include <drizzled/table_proto.h>
38
 
#include <drizzled/optimizer/range.h>
39
 
#include <drizzled/time_functions.h>
40
 
#include <drizzled/records.h>
41
 
#include <drizzled/pthread_globals.h>
42
 
#include <drizzled/internal/my_sys.h>
43
 
#include <drizzled/internal/iocache.h>
44
 
#include <drizzled/plugin/storage_engine.h>
45
 
#include <drizzled/copy_field.h>
46
 
 
47
 
#include <drizzled/transaction_services.h>
48
 
 
49
 
#include <drizzled/filesort.h>
50
 
 
51
 
#include <drizzled/message.h>
 
27
#include "drizzled/show.h"
 
28
#include "drizzled/lock.h"
 
29
#include "drizzled/session.h"
 
30
#include "drizzled/statement/alter_table.h"
 
31
#include "drizzled/global_charset_info.h"
 
32
 
 
33
 
 
34
#include "drizzled/gettext.h"
 
35
#include "drizzled/data_home.h"
 
36
#include "drizzled/sql_table.h"
 
37
#include "drizzled/table_proto.h"
 
38
#include "drizzled/optimizer/range.h"
 
39
#include "drizzled/time_functions.h"
 
40
#include "drizzled/records.h"
 
41
#include "drizzled/pthread_globals.h"
 
42
#include "drizzled/internal/my_sys.h"
 
43
#include "drizzled/internal/iocache.h"
 
44
 
 
45
#include "drizzled/transaction_services.h"
 
46
 
 
47
#include "drizzled/filesort.h"
 
48
 
 
49
#include "drizzled/message.h"
52
50
 
53
51
using namespace std;
54
52
 
77
75
 
78
76
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
79
77
 
80
 
namespace statement {
81
 
 
82
 
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
83
 
  CreateTable(in_session)
84
 
85
 
  in_session->getLex()->sql_command= SQLCOM_ALTER_TABLE;
86
 
  (void)ident;
87
 
  alter_info.build_method= build_arg;
88
 
}
89
 
 
90
 
} // namespace statement
91
 
 
92
78
bool statement::AlterTable::execute()
93
79
{
94
 
  TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
95
 
  TableList *all_tables= getSession()->getLex()->query_tables;
 
80
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
 
81
  TableList *all_tables= session->lex->query_tables;
96
82
  assert(first_table == all_tables && first_table != 0);
97
 
  Select_Lex *select_lex= &getSession()->getLex()->select_lex;
 
83
  Select_Lex *select_lex= &session->lex->select_lex;
98
84
  bool need_start_waiting= false;
99
85
 
100
86
  is_engine_set= not createTableMessage().engine().name().empty();
102
88
  if (is_engine_set)
103
89
  {
104
90
    create_info().db_type= 
105
 
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
 
91
      plugin::StorageEngine::findByName(*session, createTableMessage().engine().name());
106
92
 
107
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
               createTableMessage().engine().name().c_str());
110
97
 
111
98
      return true;
112
99
    }
119
106
  message::table::shared_ptr original_table_message;
120
107
  {
121
108
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
 
    if (not (original_table_message= plugin::StorageEngine::getTableMessage(*getSession(), identifier)))
 
109
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
123
110
    {
124
 
      my_error(ER_BAD_TABLE_ERROR, identifier);
 
111
      std::string path;
 
112
      identifier.getSQLPath(path);
 
113
      my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
125
114
      return true;
126
115
    }
127
116
 
128
117
    if (not  create_info().db_type)
129
118
    {
130
119
      create_info().db_type= 
131
 
        plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
 
120
        plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
132
121
 
133
122
      if (not create_info().db_type)
134
123
      {
135
 
        my_error(ER_BAD_TABLE_ERROR, identifier);
 
124
        std::string path;
 
125
        identifier.getSQLPath(path);
 
126
        my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
136
127
        return true;
137
128
      }
138
129
    }
141
132
  if (not validateCreateTableOption())
142
133
    return true;
143
134
 
144
 
  if (getSession()->inTransaction())
145
 
  {
146
 
    my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
 
135
  /* ALTER TABLE ends previous transaction */
 
136
  if (not session->endActiveTransaction())
147
137
    return true;
148
 
  }
149
138
 
150
 
  if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
 
139
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
151
140
    return true;
152
141
 
153
142
  bool res;
155
144
  {
156
145
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
146
    identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
158
 
                                   getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName());
 
147
                                   session->lex->name.str ? session->lex->name.str : first_table->getTableName());
159
148
 
160
 
    res= alter_table(getSession(), 
 
149
    res= alter_table(session, 
161
150
                     identifier,
162
151
                     new_identifier,
163
152
                     &create_info(),
167
156
                     &alter_info,
168
157
                     select_lex->order_list.elements,
169
158
                     (Order *) select_lex->order_list.first,
170
 
                     getSession()->getLex()->ignore);
 
159
                     session->lex->ignore);
171
160
  }
172
161
  else
173
162
  {
174
163
    identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
 
    Table *table= getSession()->find_temporary_table(catch22);
 
164
    Table *table= session->find_temporary_table(catch22);
176
165
    assert(table);
177
166
    {
178
167
      identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
168
      identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
180
 
                                       getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName(),
181
 
                                       table->getMutableShare()->getPath());
 
169
                                     session->lex->name.str ? session->lex->name.str : first_table->getTableName(),
 
170
                                     table->getMutableShare()->getPath());
182
171
 
183
 
      res= alter_table(getSession(), 
 
172
      res= alter_table(session, 
184
173
                       identifier,
185
174
                       new_identifier,
186
175
                       &create_info(),
190
179
                       &alter_info,
191
180
                       select_lex->order_list.elements,
192
181
                       (Order *) select_lex->order_list.first,
193
 
                       getSession()->getLex()->ignore);
 
182
                       session->lex->ignore);
194
183
    }
195
184
  }
196
185
 
198
187
     Release the protection against the global read lock and wake
199
188
     everyone, who might want to set a global read lock.
200
189
   */
201
 
  getSession()->startWaitingGlobalReadLock();
 
190
  session->startWaitingGlobalReadLock();
202
191
 
203
192
  return res;
204
193
}
245
234
  @retval false  success
246
235
*/
247
236
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)
 
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;
256
245
  /* New key definitions are added here */
257
246
  List<Key> new_key_list;
258
 
  List<AlterDrop>::iterator drop_it(alter_info->drop_list.begin());
259
 
  List<CreateField>::iterator def_it(alter_info->create_list.begin());
260
 
  List<AlterColumn>::iterator alter_it(alter_info->alter_list.begin());
261
 
  List<Key>::iterator key_it(alter_info->key_list.begin());
262
 
  List<CreateField>::iterator find_it(new_create_list.begin());
263
 
  List<CreateField>::iterator field_it(new_create_list.begin());
 
247
  List_iterator<AlterDrop> drop_it(alter_info->drop_list);
 
248
  List_iterator<CreateField> def_it(alter_info->create_list);
 
249
  List_iterator<AlterColumn> alter_it(alter_info->alter_list);
 
250
  List_iterator<Key> key_it(alter_info->key_list);
 
251
  List_iterator<CreateField> find_it(new_create_list);
 
252
  List_iterator<CreateField> field_it(new_create_list);
264
253
  List<Key_part_spec> key_parts;
265
254
  uint32_t used_fields= create_info->used_fields;
266
255
  KeyInfo *key_info= table->key_info;
291
280
  {
292
281
    /* Check if field should be dropped */
293
282
    AlterDrop *drop;
294
 
    drop_it= alter_info->drop_list.begin();
 
283
    drop_it.rewind();
295
284
    while ((drop= drop_it++))
296
285
    {
297
286
      if (drop->type == AlterDrop::COLUMN &&
318
307
    field->setReadSet();
319
308
 
320
309
    /* Check if field is changed */
321
 
    def_it= alter_info->create_list.begin();
 
310
    def_it.rewind();
322
311
    while ((def= def_it++))
323
312
    {
324
313
      if (def->change &&
344
333
      */
345
334
      def= new CreateField(field, field);
346
335
      new_create_list.push_back(def);
347
 
      alter_it= alter_info->alter_list.begin(); /* Change default if ALTER */
 
336
      alter_it.rewind(); /* Change default if ALTER */
348
337
      AlterColumn *alter;
349
338
 
350
339
      while ((alter= alter_it++))
375
364
    }
376
365
  }
377
366
 
378
 
  def_it= alter_info->create_list.begin();
 
367
  def_it.rewind();
379
368
  while ((def= def_it++)) /* Add new columns */
380
369
  {
381
370
    if (def->change && ! def->field)
401
390
    else
402
391
    {
403
392
      CreateField *find;
404
 
      find_it= new_create_list.begin();
 
393
      find_it.rewind();
405
394
 
406
395
      while ((find= find_it++)) /* Add new columns */
407
396
      {
429
418
      */
430
419
      if (alter_info->build_method == HA_BUILD_ONLINE)
431
420
      {
432
 
        my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
 
421
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
433
422
        return true;
434
423
      }
435
424
 
463
452
    char *key_name= key_info->name;
464
453
    AlterDrop *drop;
465
454
 
466
 
    drop_it= alter_info->drop_list.begin();
 
455
    drop_it.rewind();
467
456
    while ((drop= drop_it++))
468
457
    {
469
458
      if (drop->type == AlterDrop::KEY &&
478
467
    }
479
468
 
480
469
    KeyPartInfo *key_part= key_info->key_part;
481
 
    key_parts.clear();
 
470
    key_parts.empty();
482
471
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
483
472
    {
484
473
      if (! key_part->field)
486
475
 
487
476
      const char *key_part_name= key_part->field->field_name;
488
477
      CreateField *cfield;
489
 
      field_it= new_create_list.begin();
 
478
      field_it.rewind();
490
479
      while ((cfield= field_it++))
491
480
      {
492
481
        if (cfield->change)
530
519
    }
531
520
    if (key_parts.elements)
532
521
    {
533
 
      key_create_information_st key_create_info= default_key_create_info;
 
522
      key_create_information_st key_create_info;
534
523
      Key *key;
535
 
      Key::Keytype key_type;
 
524
      enum Key::Keytype key_type;
 
525
      memset(&key_create_info, 0, sizeof(key_create_info));
536
526
 
537
527
      key_create_info.algorithm= key_info->algorithm;
538
 
 
539
528
      if (key_info->flags & HA_USES_BLOCK_SIZE)
540
529
        key_create_info.block_size= key_info->block_size;
541
 
 
542
530
      if (key_info->flags & HA_USES_COMMENT)
543
531
        key_create_info.comment= key_info->comment;
544
532
 
550
538
          key_type= Key::UNIQUE;
551
539
      }
552
540
      else
553
 
      {
554
541
        key_type= Key::MULTIPLE;
555
 
      }
556
542
 
557
543
      key= new Key(key_type,
558
544
                   key_name,
568
554
  for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
569
555
  {
570
556
    AlterDrop *drop;
571
 
    drop_it= alter_info->drop_list.begin();
 
557
    drop_it.rewind();
572
558
    while ((drop= drop_it++))
573
559
    {
574
560
      if (drop->type == AlterDrop::FOREIGN_KEY &&
666
652
    table_message.set_type(message::Table::TEMPORARY);
667
653
  }
668
654
 
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());
 
655
  table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
 
656
  table_message.set_version(table->getShare()->getTableProto()->version());
 
657
  table_message.set_uuid(table->getShare()->getTableProto()->uuid());
672
658
 
673
659
  rc= false;
674
660
  alter_info->create_list.swap(new_create_list);
723
709
   We set this flag so that ha_innobase::open and ::external_lock() do
724
710
   not complain when we lock the table
725
711
 */
726
 
  session->setDoingTablespaceOperation(true);
 
712
  session->tablespace_op= true;
727
713
  if (not (table= session->openTableLock(table_list, TL_WRITE)))
728
714
  {
729
 
    session->setDoingTablespaceOperation(false);
 
715
    session->tablespace_op= false;
730
716
    return -1;
731
717
  }
732
718
 
740
726
      break;
741
727
 
742
728
    /* The ALTER Table is always in its own transaction */
743
 
    error= transaction_services.autocommitOrRollback(*session, false);
 
729
    error= transaction_services.autocommitOrRollback(session, false);
744
730
    if (not session->endActiveTransaction())
745
731
      error= 1;
746
732
 
751
737
 
752
738
  } while(0);
753
739
 
754
 
  (void) transaction_services.autocommitOrRollback(*session, error);
755
 
  session->setDoingTablespaceOperation(false);
 
740
  (void) transaction_services.autocommitOrRollback(session, error);
 
741
  session->tablespace_op=false;
756
742
 
757
743
  if (error == 0)
758
744
  {
824
810
 
825
811
      if (session.find_temporary_table(new_table_identifier))
826
812
      {
827
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
813
        std::string path;
 
814
        new_table_identifier.getSQLPath(path);
 
815
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
828
816
        return false;
829
817
      }
830
818
    }
961
949
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
950
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
963
951
  {
964
 
    my_error(ER_ILLEGAL_HA, new_table_identifier);
 
952
    std::string path;
 
953
    new_table_identifier.getSQLPath(path);
 
954
    my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
965
955
 
966
956
    return true;
967
957
  }
1482
1472
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
1483
1473
 
1484
1474
  /* We can abort alter table for any table type */
1485
 
  session->setAbortOnWarning(not ignore);
 
1475
  session->abort_on_warning= !ignore;
1486
1476
 
1487
1477
  from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
1478
  to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
1489
1479
 
1490
 
  List<CreateField>::iterator it(create.begin());
 
1480
  List_iterator<CreateField> it(create);
1491
1481
  CreateField *def;
1492
1482
  copy_end= copy;
1493
1483
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
1525
1515
        from->sort.io_cache= new internal::IO_CACHE;
1526
1516
 
1527
1517
        tables.table= from;
1528
 
        tables.setTableName(from->getMutableShare()->getTableName());
1529
 
        tables.alias= tables.getTableName();
 
1518
        tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
 
1519
        tables.alias= const_cast<char *>(tables.getTableName());
1530
1520
        tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1531
1521
        error= 1;
1532
1522
 
1533
 
        if (session->getLex()->select_lex.setup_ref_array(session, order_num) ||
1534
 
            setup_order(session, session->getLex()->select_lex.ref_pointer_array,
 
1523
        if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
1524
            setup_order(session, session->lex->select_lex.ref_pointer_array,
1535
1525
                        &tables, fields, all_fields, order) ||
1536
1526
            !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1537
1527
            (from->sort.found_records= filesort.run(from, sortorder, length,
1638
1628
      Ensure that the new table is saved properly to disk so that we
1639
1629
      can do a rename
1640
1630
    */
1641
 
    if (transaction_services.autocommitOrRollback(*session, false))
 
1631
    if (transaction_services.autocommitOrRollback(session, false))
1642
1632
      error= 1;
1643
1633
 
1644
1634
    if (not session->endActiveTransaction())
1646
1636
 
1647
1637
  } while (0);
1648
1638
 
1649
 
  session->setAbortOnWarning(false);
 
1639
  session->abort_on_warning= 0;
1650
1640
  from->free_io_cache();
1651
1641
  *copied= found_count;
1652
1642
  *deleted=delete_count;