~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Djellel E. Difallah
  • Date: 2010-03-27 10:10:49 UTC
  • mto: This revision was merged to the branch mainline in revision 1429.
  • Revision ID: ded@ubuntu-20100327101049-oo3arvatjoyku124
merge my_decimal and decimal

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