~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Joe Daly
  • Date: 2010-05-21 02:16:56 UTC
  • mto: This revision was merged to the branch mainline in revision 1555.
  • Revision ID: skinny.moey@gmail.com-20100521021656-bx6piitfh77jnl28
add statistics_variables.h

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