~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-08-08 04:22:33 UTC
  • mto: (1115.3.4 captain)
  • mto: This revision was merged to the branch mainline in revision 1117.
  • Revision ID: osullivan.padraig@gmail.com-20090808042233-q0z88zc490z3f3r7
Renamed the Command class to be Statement. Renamed the command directory to
statement and also the command header file to statement. Updated various
source files to reflect this renaming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
18
 
#include "config.h"
 
18
#include <drizzled/server_includes.h>
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/data_home.h>
24
24
#include <drizzled/sql_parse.h>
25
 
#include <drizzled/my_hash.h>
 
25
#include <mysys/hash.h>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
 
#include "drizzled/strfunc.h"
30
29
#include <drizzled/db.h>
31
30
#include <drizzled/lock.h>
32
31
#include <drizzled/unireg.h>
33
32
#include <drizzled/item/int.h>
34
33
#include <drizzled/item/empty_string.h>
35
 
#include <drizzled/transaction_services.h>
36
 
#include "drizzled/transaction_services.h"
 
34
#include <drizzled/replication_services.h>
37
35
#include <drizzled/table_proto.h>
38
 
#include <drizzled/plugin/client.h>
39
 
#include <drizzled/table_identifier.h>
40
 
#include "drizzled/internal/m_string.h"
41
 
#include "drizzled/global_charset_info.h"
42
 
#include "drizzled/charset.h"
43
 
 
44
 
 
45
 
#include "drizzled/statement/alter_table.h"
46
 
#include "drizzled/sql_table.h"
47
 
#include "drizzled/pthread_globals.h"
48
36
 
49
37
#include <algorithm>
50
 
#include <sstream>
51
38
 
52
39
using namespace std;
53
 
 
54
 
namespace drizzled
55
 
{
56
 
 
57
 
extern plugin::StorageEngine *myisam_engine;
58
 
extern pid_t current_pid;
59
 
 
 
40
extern drizzled::ReplicationServices replication_services;
 
41
 
 
42
static const char hexchars[]= "0123456789abcdef";
60
43
bool is_primary_key(KEY *key_info)
61
44
{
62
45
  static const char * primary_key_name="PRIMARY";
74
57
 
75
58
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
76
59
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
 
60
static int copy_data_between_tables(Table *from,Table *to,
 
61
                                    List<CreateField> &create, bool ignore,
 
62
                                    uint32_t order_num, order_st *order,
 
63
                                    ha_rows *copied,ha_rows *deleted,
 
64
                                    enum enum_enable_or_disable keys_onoff,
 
65
                                    bool error_if_not_empty);
77
66
 
78
67
static bool prepare_blob_field(Session *session, CreateField *sql_field);
 
68
static bool check_engine(Session *, const char *, HA_CREATE_INFO *);
 
69
static int
 
70
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
 
71
                           Alter_info *alter_info,
 
72
                           bool tmp_table,
 
73
                               uint32_t *db_options,
 
74
                               handler *file, KEY **key_info_buffer,
 
75
                               uint32_t *key_count, int select_field_count);
 
76
static bool
 
77
mysql_prepare_alter_table(Session *session, Table *table,
 
78
                          HA_CREATE_INFO *create_info,
 
79
                          Alter_info *alter_info);
79
80
 
80
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
 
81
static void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
81
82
{
82
83
  /*
83
84
    If the table character set was not given explicitly,
84
85
    let's fetch the database default character set and
85
86
    apply it to the table.
86
87
  */
87
 
  SchemaIdentifier identifier(db);
88
88
  if (create_info->default_table_charset == NULL)
89
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
89
    create_info->default_table_charset= get_default_db_collation(db);
 
90
}
 
91
 
 
92
/*
 
93
  Translate a file name to a table name (WL #1324).
 
94
 
 
95
  SYNOPSIS
 
96
    filename_to_tablename()
 
97
      from                      The file name
 
98
      to                OUT     The table name
 
99
      to_length                 The size of the table name buffer.
 
100
 
 
101
  RETURN
 
102
    Table name length.
 
103
*/
 
104
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
105
{
 
106
  uint32_t length= 0;
 
107
 
 
108
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
109
  {
 
110
    /* Temporary table name. */
 
111
    length= strlen(strncpy(to, from, to_length));
 
112
  }
 
113
  else
 
114
  {
 
115
    for (; *from  && length < to_length; length++, from++)
 
116
    {
 
117
      if (*from != '@')
 
118
      {
 
119
        to[length]= *from;
 
120
        continue;
 
121
      }
 
122
      /* We've found an escaped char - skip the @ */
 
123
      from++;
 
124
      to[length]= 0;
 
125
      /* There will be a two-position hex-char version of the char */
 
126
      for (int x=1; x >= 0; x--)
 
127
      {
 
128
        if (*from >= '0' && *from <= '9')
 
129
          to[length] += ((*from++ - '0') << (4 * x));
 
130
        else if (*from >= 'a' && *from <= 'f')
 
131
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
132
      }
 
133
      /* Backup because we advanced extra in the inner loop */
 
134
      from--;
 
135
    } 
 
136
  }
 
137
 
 
138
  return length;
 
139
}
 
140
 
 
141
 
 
142
/*
 
143
  Translate a table name to a file name (WL #1324).
 
144
 
 
145
  SYNOPSIS
 
146
    tablename_to_filename()
 
147
      from                      The table name
 
148
      to                OUT     The file name
 
149
      to_length                 The size of the file name buffer.
 
150
 
 
151
  RETURN
 
152
    true if errors happen. false on success.
 
153
*/
 
154
bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
155
{
 
156
  
 
157
  size_t length= 0;
 
158
  for (; *from  && length < to_length; length++, from++)
 
159
  {
 
160
    if ((*from >= '0' && *from <= '9') ||
 
161
        (*from >= 'A' && *from <= 'Z') ||
 
162
        (*from >= 'a' && *from <= 'z') ||
 
163
/* OSX defines an extra set of high-bit and multi-byte characters
 
164
   that cannot be used on the filesystem. Instead of trying to sort
 
165
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
166
   It won't really hurt anything - it'll just make some filenames ugly. */
 
167
#if !defined(TARGET_OS_OSX)
 
168
        ((unsigned char)*from >= 128) ||
 
169
#endif
 
170
        (*from == '_') ||
 
171
        (*from == ' ') ||
 
172
        (*from == '-'))
 
173
    {
 
174
      to[length]= *from;
 
175
      continue;
 
176
    }
 
177
   
 
178
    if (length + 3 >= to_length)
 
179
      return true;
 
180
 
 
181
    /* We need to escape this char in a way that can be reversed */
 
182
    to[length++]= '@';
 
183
    to[length++]= hexchars[(*from >> 4) & 15];
 
184
    to[length]= hexchars[(*from) & 15];
 
185
  }
 
186
 
 
187
  if (check_if_legal_tablename(to) &&
 
188
      length + 4 < to_length)
 
189
  {
 
190
    memcpy(to + length, "@@@", 4);
 
191
    length+= 3;
 
192
  }
 
193
  return false;
 
194
}
 
195
 
 
196
 
 
197
/*
 
198
  Creates path to a file: drizzle_data_dir/db/table.ext
 
199
 
 
200
  SYNOPSIS
 
201
   build_table_filename()
 
202
     buff                       Where to write result
 
203
                                This may be the same as table_name.
 
204
     bufflen                    buff size
 
205
     db                         Database name
 
206
     table_name                 Table name
 
207
     ext                        File extension.
 
208
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
209
                                table_name is temporary, do not change.
 
210
 
 
211
  NOTES
 
212
 
 
213
    Uses database and table name, and extension to create
 
214
    a file name in drizzle_data_dir. Database and table
 
215
    names are converted from system_charset_info into "fscs".
 
216
    Unless flags indicate a temporary table name.
 
217
    'db' is always converted.
 
218
    'ext' is not converted.
 
219
 
 
220
    The conversion suppression is required for ALTER Table. This
 
221
    statement creates intermediate tables. These are regular
 
222
    (non-temporary) tables with a temporary name. Their path names must
 
223
    be derivable from the table name. So we cannot use
 
224
    build_tmptable_filename() for them.
 
225
 
 
226
  RETURN
 
227
    path length on success, 0 on failure
 
228
*/
 
229
 
 
230
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
 
231
{
 
232
  char dbbuff[FN_REFLEN];
 
233
  char tbbuff[FN_REFLEN];
 
234
  bool conversion_error= false;
 
235
 
 
236
  memset(tbbuff, 0, sizeof(tbbuff));
 
237
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
238
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
239
  else
 
240
  {
 
241
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
242
    if (conversion_error)
 
243
    {
 
244
      errmsg_printf(ERRMSG_LVL_ERROR,
 
245
                    _("Table name cannot be encoded and fit within filesystem "
 
246
                      "name length restrictions."));
 
247
      return 0;
 
248
    }
 
249
  }
 
250
  memset(dbbuff, 0, sizeof(dbbuff));
 
251
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
252
  if (conversion_error)
 
253
  {
 
254
    errmsg_printf(ERRMSG_LVL_ERROR,
 
255
                  _("Schema name cannot be encoded and fit within filesystem "
 
256
                    "name length restrictions."));
 
257
    return 0;
 
258
  }
 
259
   
 
260
 
 
261
  int rootdir_len= strlen(FN_ROOTDIR);
 
262
  string table_path(drizzle_data_home);
 
263
  int without_rootdir= table_path.length()-rootdir_len;
 
264
 
 
265
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
266
  if (without_rootdir >= 0)
 
267
  {
 
268
    const char *tmp= table_path.c_str()+without_rootdir;
 
269
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
270
      table_path.append(FN_ROOTDIR);
 
271
  }
 
272
 
 
273
  table_path.append(dbbuff);
 
274
  table_path.append(FN_ROOTDIR);
 
275
  table_path.append(tbbuff);
 
276
 
 
277
  if (bufflen < table_path.length())
 
278
    return 0;
 
279
 
 
280
  strcpy(buff, table_path.c_str());
 
281
 
 
282
  return table_path.length();
 
283
}
 
284
 
 
285
 
 
286
/*
 
287
  Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
 
288
 
 
289
  SYNOPSIS
 
290
   build_tmptable_filename()
 
291
     session                    The thread handle.
 
292
     buff                       Where to write result
 
293
     bufflen                    buff size
 
294
 
 
295
  NOTES
 
296
 
 
297
    Uses current_pid, thread_id, and tmp_table counter to create
 
298
    a file name in drizzle_tmpdir.
 
299
 
 
300
  RETURN
 
301
    path length on success, 0 on failure
 
302
*/
 
303
 
 
304
static uint32_t build_tmptable_filename(Session* session,
 
305
                                        char *buff, size_t bufflen)
 
306
{
 
307
  uint32_t length;
 
308
  ostringstream path_str, post_tmpdir_str;
 
309
  string tmp;
 
310
 
 
311
  path_str << drizzle_tmpdir;
 
312
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
313
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
314
  tmp= post_tmpdir_str.str();
 
315
 
 
316
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
317
 
 
318
  path_str << tmp;
 
319
 
 
320
  if (bufflen < path_str.str().length())
 
321
    length= 0;
 
322
  else
 
323
    length= unpack_filename(buff, path_str.str().c_str());
 
324
 
 
325
  return length;
90
326
}
91
327
 
92
328
/*
93
329
  SYNOPSIS
94
330
    write_bin_log()
95
331
    session                           Thread object
 
332
    clear_error                   is clear_error to be called
96
333
    query                         Query to log
97
334
    query_length                  Length of query
98
335
 
101
338
 
102
339
  DESCRIPTION
103
340
    Write the binlog if open, routine used in multiple places in this
104
 
    cursor
 
341
    file
105
342
*/
106
343
 
107
 
void write_bin_log(Session *session,
108
 
                   char const *query)
 
344
void write_bin_log(Session *session, bool,
 
345
                   char const *query, size_t query_length)
109
346
{
110
 
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(session, query);
 
347
  replication_services.rawStatement(session, query, query_length);
112
348
}
113
349
 
114
350
 
115
 
/* Should should be refactored to go away */
116
 
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
351
/*
 
352
 delete (drop) tables.
 
353
 
 
354
  SYNOPSIS
 
355
   mysql_rm_table()
 
356
   session                      Thread handle
 
357
   tables               List of tables to delete
 
358
   if_exists            If 1, don't give error if one table doesn't exists
 
359
 
 
360
  NOTES
 
361
    Will delete all tables that can be deleted and give a compact error
 
362
    messages for tables that could not be deleted.
 
363
    If a table is in use, we will wait for all users to free the table
 
364
    before dropping it
 
365
 
 
366
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
367
    not if under LOCK TABLES.
 
368
 
 
369
  RETURN
 
370
    false OK.  In this case ok packet is sent to user
 
371
    true  Error
 
372
 
 
373
*/
 
374
 
 
375
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
117
376
{
118
 
  TransactionServices &transaction_services= TransactionServices::singleton();
119
 
  string built_query;
120
 
 
121
 
  if (if_exists)
122
 
    built_query.append("DROP TABLE IF EXISTS ");
123
 
  else
124
 
    built_query.append("DROP TABLE ");
125
 
 
126
 
  built_query.append("`");
127
 
  if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
128
 
  {
129
 
    built_query.append(db_name);
130
 
    built_query.append("`.`");
131
 
  }
132
 
 
133
 
  built_query.append(table_name);
134
 
  built_query.append("`");
135
 
  transaction_services.rawStatement(session, built_query);
 
377
  bool error, need_start_waiting= false;
 
378
 
 
379
  if (tables && tables->schema_table)
 
380
  {
 
381
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
382
    return(true);
 
383
  }
 
384
 
 
385
  /* mark for close and remove all cached entries */
 
386
 
 
387
  if (!drop_temporary)
 
388
  {
 
389
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
390
      return(true);
 
391
  }
 
392
 
 
393
  /*
 
394
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
395
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
396
    close their tables. This would make a pretty deadlock.
 
397
  */
 
398
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, 0);
 
399
 
 
400
  if (need_start_waiting)
 
401
    start_waiting_global_read_lock(session);
 
402
 
 
403
  if (error)
 
404
    return(true);
 
405
  session->my_ok();
 
406
  return(false);
136
407
}
137
408
 
138
409
/*
140
411
 
141
412
  SYNOPSIS
142
413
    mysql_rm_table_part2()
143
 
    session                     Thread Cursor
 
414
    session                     Thread handler
144
415
    tables              Tables to drop
145
416
    if_exists           If set, don't give an error if table doesn't exists.
146
417
                        In this case we give an warning of level 'NOTE'
147
418
    drop_temporary      Only drop temporary tables
 
419
    drop_view           Allow to delete VIEW .frm
 
420
    dont_log_query      Don't write query to log files. This will also not
 
421
                        generate warnings if the handler files doesn't exists
148
422
 
149
423
  TODO:
150
424
    When logging to the binary log, we should log
163
437
*/
164
438
 
165
439
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
166
 
                         bool drop_temporary)
 
440
                         bool drop_temporary, bool dont_log_query)
167
441
{
168
442
  TableList *table;
 
443
  char path[FN_REFLEN];
 
444
  uint32_t path_length= 0;
169
445
  String wrong_tables;
170
446
  int error= 0;
171
 
  bool foreign_key_error= false;
 
447
  int non_temp_tables_count= 0;
 
448
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
 
449
  String built_query;
 
450
 
 
451
  if (!dont_log_query)
 
452
  {
 
453
    built_query.set_charset(system_charset_info);
 
454
    if (if_exists)
 
455
      built_query.append("DROP Table IF EXISTS ");
 
456
    else
 
457
      built_query.append("DROP Table ");
 
458
  }
172
459
 
173
460
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
174
461
 
175
462
  /*
176
463
    If we have the table in the definition cache, we don't have to check the
177
 
    .frm cursor to find if the table is a normal table (not view) and what
 
464
    .frm file to find if the table is a normal table (not view) and what
178
465
    engine to use.
179
466
  */
180
467
 
181
468
  for (table= tables; table; table= table->next_local)
182
469
  {
183
 
    TableIdentifier identifier(table->db, table->table_name);
184
470
    TableShare *share;
185
471
    table->db_type= NULL;
186
 
 
187
 
    if ((share= TableShare::getShare(identifier)))
188
 
    {
 
472
    if ((share= TableShare::getShare(table->db, table->table_name)))
189
473
      table->db_type= share->db_type();
190
 
    }
191
474
  }
192
475
 
193
 
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
476
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
194
477
  {
195
478
    pthread_mutex_unlock(&LOCK_open);
196
479
    return 1;
202
485
  for (table= tables; table; table= table->next_local)
203
486
  {
204
487
    char *db=table->db;
 
488
    StorageEngine *table_type;
205
489
 
206
490
    error= session->drop_temporary_table(table);
207
491
 
208
492
    switch (error) {
209
493
    case  0:
210
494
      // removed temporary table
 
495
      tmp_table_deleted= 1;
211
496
      continue;
212
497
    case -1:
213
498
      error= 1;
217
502
      error= 0;
218
503
    }
219
504
 
220
 
    if (drop_temporary == false)
 
505
    /*
 
506
      If row-based replication is used and the table is not a
 
507
      temporary table, we add the table name to the drop statement
 
508
      being built.  The string always end in a comma and the comma
 
509
      will be chopped off before being written to the binary log.
 
510
      */
 
511
    if (!dont_log_query)
 
512
    {
 
513
      non_temp_tables_count++;
 
514
      /*
 
515
        Don't write the database name if it is the current one (or if
 
516
        session->db is NULL).
 
517
      */
 
518
      built_query.append("`");
 
519
      if (session->db == NULL || strcmp(db,session->db) != 0)
 
520
      {
 
521
        built_query.append(db);
 
522
        built_query.append("`.`");
 
523
      }
 
524
 
 
525
      built_query.append(table->table_name);
 
526
      built_query.append("`,");
 
527
    }
 
528
 
 
529
    table_type= table->db_type;
 
530
    if (!drop_temporary)
221
531
    {
222
532
      Table *locked_table;
223
533
      abort_locked_tables(session, db, table->table_name);
236
546
        error= -1;
237
547
        goto err_with_placeholders;
238
548
      }
 
549
      /* remove .frm file and engine files */
 
550
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
239
551
    }
240
 
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? message::Table::INTERNAL : message::Table::STANDARD);
241
 
 
242
 
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
552
    if (drop_temporary ||
 
553
        ((table_type == NULL
 
554
          && (StorageEngine::getTableProto(path, NULL) != EEXIST))))
243
555
    {
244
556
      // Table was not found on disk and table can't be created from engine
245
557
      if (if_exists)
251
563
    }
252
564
    else
253
565
    {
254
 
      error= plugin::StorageEngine::dropTable(*session, identifier);
255
 
 
256
 
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
566
      error= ha_delete_table(session, path, db, table->table_name,
 
567
                             !dont_log_query);
 
568
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
 
569
          if_exists)
257
570
      {
258
 
        error= 0;
 
571
        error= 0;
259
572
        session->clear_error();
260
573
      }
261
 
 
262
574
      if (error == HA_ERR_ROW_IS_REFERENCED)
263
575
      {
264
576
        /* the table is referenced by a foreign key constraint */
265
 
        foreign_key_error= true;
266
 
      }
267
 
    }
268
 
 
269
 
    if (error == 0 || (if_exists && foreign_key_error == false))
270
 
    {
271
 
      TransactionServices &transaction_services= TransactionServices::singleton();
272
 
      transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
273
 
    }
274
 
 
 
577
        foreign_key_error=1;
 
578
      }
 
579
      if (error == 0)
 
580
      {
 
581
          some_tables_deleted=1;
 
582
      }
 
583
    }
275
584
    if (error)
276
585
    {
277
586
      if (wrong_tables.length())
285
594
  */
286
595
  pthread_mutex_unlock(&LOCK_open);
287
596
  error= 0;
288
 
 
289
597
  if (wrong_tables.length())
290
598
  {
291
 
    if (not foreign_key_error)
292
 
    {
 
599
    if (!foreign_key_error)
293
600
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
294
601
                      wrong_tables.c_ptr());
295
 
    }
296
602
    else
297
603
    {
298
604
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
300
606
    error= 1;
301
607
  }
302
608
 
 
609
  if (some_tables_deleted || tmp_table_deleted || !error)
 
610
  {
 
611
    if (!dont_log_query)
 
612
    {
 
613
      if ((non_temp_tables_count > 0 && !tmp_table_deleted))
 
614
      {
 
615
        /*
 
616
          In this case, we are either using statement-based
 
617
          replication or using row-based replication but have only
 
618
          deleted one or more non-temporary tables (and no temporary
 
619
          tables).  In this case, we can write the original query into
 
620
          the binary log.
 
621
         */
 
622
        write_bin_log(session, !error, session->query, session->query_length);
 
623
      }
 
624
      else if (non_temp_tables_count > 0 &&
 
625
               tmp_table_deleted)
 
626
      {
 
627
        /*
 
628
          In this case we have deleted both temporary and
 
629
          non-temporary tables, so:
 
630
          - since we have deleted a non-temporary table we have to
 
631
            binlog the statement, but
 
632
          - since we have deleted a temporary table we cannot binlog
 
633
            the statement (since the table has not been created on the
 
634
            slave, this might cause the slave to stop).
 
635
 
 
636
          Instead, we write a built statement, only containing the
 
637
          non-temporary tables, to the binary log
 
638
        */
 
639
        built_query.chop();                  // Chop of the last comma
 
640
        built_query.append(" /* generated by server */");
 
641
        write_bin_log(session, !error, built_query.ptr(), built_query.length());
 
642
      }
 
643
      /*
 
644
        The remaining cases are:
 
645
        - no tables where deleted and
 
646
        - only temporary tables where deleted and row-based
 
647
          replication is used.
 
648
        In both these cases, nothing should be written to the binary
 
649
        log.
 
650
      */
 
651
    }
 
652
  }
303
653
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
304
 
 
305
654
err_with_placeholders:
306
655
  unlock_table_names(tables, NULL);
307
656
  pthread_mutex_unlock(&LOCK_open);
308
657
  session->no_warnings_for_error= 0;
309
658
 
310
 
  return error;
 
659
  return(error);
311
660
}
312
661
 
313
662
 
316
665
 
317
666
  SYNOPSIS
318
667
    quick_rm_table()
319
 
      base                      The plugin::StorageEngine handle.
 
668
      base                      The StorageEngine handle.
320
669
      db                        The database name.
321
670
      table_name                The table name.
322
671
      is_tmp                    If the table is temp.
325
674
    0           OK
326
675
    != 0        Error
327
676
*/
328
 
bool quick_rm_table(Session& session,
329
 
                    TableIdentifier &identifier)
 
677
 
 
678
bool quick_rm_table(StorageEngine *, const char *db,
 
679
                    const char *table_name, bool is_tmp)
330
680
{
331
 
  return (plugin::StorageEngine::dropTable(session, identifier));
 
681
  char path[FN_REFLEN];
 
682
  bool error= 0;
 
683
 
 
684
  build_table_filename(path, sizeof(path), db, table_name, is_tmp);
 
685
 
 
686
  return(ha_delete_table(current_session, path, db, table_name, 0) ||
 
687
              error);
332
688
}
333
689
 
334
690
/*
457
813
  }
458
814
}
459
815
 
 
816
 
460
817
/*
461
818
  Prepare a create_table instance for packing
462
819
 
465
822
    sql_field     field to prepare for packing
466
823
    blob_columns  count for BLOBs
467
824
    timestamps    count for timestamps
 
825
    table_flags   table flags
468
826
 
469
827
  DESCRIPTION
470
828
    This function prepares a CreateField instance.
474
832
   0    ok
475
833
   1    Error
476
834
*/
 
835
 
477
836
int prepare_create_field(CreateField *sql_field,
478
837
                         uint32_t *blob_columns,
479
 
                         int *timestamps,
480
 
                         int *timestamps_with_niladic)
 
838
                         int *timestamps, int *timestamps_with_niladic,
 
839
                         int64_t )
481
840
{
482
841
  unsigned int dup_val_count;
483
842
 
489
848
 
490
849
  switch (sql_field->sql_type) {
491
850
  case DRIZZLE_TYPE_BLOB:
492
 
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
493
 
    sql_field->length= 8; // Unireg field length
 
851
    sql_field->pack_flag=FIELDFLAG_BLOB |
 
852
      pack_length_to_packflag(sql_field->pack_length -
 
853
                              portable_sizeof_char_ptr);
 
854
    if (sql_field->charset->state & MY_CS_BINSORT)
 
855
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
856
    sql_field->length=8;                        // Unireg field length
494
857
    (*blob_columns)++;
495
858
    break;
496
859
  case DRIZZLE_TYPE_VARCHAR:
497
860
    sql_field->pack_flag=0;
 
861
    if (sql_field->charset->state & MY_CS_BINSORT)
 
862
      sql_field->pack_flag|=FIELDFLAG_BINARY;
498
863
    break;
499
864
  case DRIZZLE_TYPE_ENUM:
500
 
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
501
 
    if (check_duplicates_in_interval("ENUM",
502
 
                                     sql_field->field_name,
503
 
                                     sql_field->interval,
504
 
                                     sql_field->charset,
505
 
                                     &dup_val_count))
 
865
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
866
      FIELDFLAG_INTERVAL;
 
867
    if (sql_field->charset->state & MY_CS_BINSORT)
 
868
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
869
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
 
870
                                 sql_field->interval,
 
871
                                     sql_field->charset, &dup_val_count))
506
872
      return 1;
507
873
    break;
508
874
  case DRIZZLE_TYPE_DATE:  // Rest of string types
510
876
  case DRIZZLE_TYPE_NULL:
511
877
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
512
878
    break;
513
 
  case DRIZZLE_TYPE_DECIMAL:
514
 
    sql_field->pack_flag= 0;
 
879
  case DRIZZLE_TYPE_NEWDECIMAL:
 
880
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
881
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
882
                           FIELDFLAG_DECIMAL) |
 
883
                          (sql_field->flags & DECIMAL_FLAG ?  FIELDFLAG_DECIMAL_POSITION : 0) |
 
884
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
515
885
    break;
516
886
  case DRIZZLE_TYPE_TIMESTAMP:
517
887
    /* We should replace old TIMESTAMP fields with their newer analogs */
531
901
    (*timestamps)++;
532
902
    /* fall-through */
533
903
  default:
534
 
    sql_field->pack_flag=(0 |
535
 
                          f_settype((uint32_t) sql_field->sql_type));
 
904
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
905
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
906
                           FIELDFLAG_DECIMAL) |
 
907
                          f_settype((uint32_t) sql_field->sql_type) |
 
908
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
536
909
    break;
537
910
  }
 
911
  if (!(sql_field->flags & NOT_NULL_FLAG))
 
912
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
 
913
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
 
914
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
538
915
  return 0;
539
916
}
540
917
 
541
 
static int mysql_prepare_create_table(Session *session,
542
 
                                      HA_CREATE_INFO *create_info,
543
 
                                      message::Table &create_proto,
544
 
                                      AlterInfo *alter_info,
545
 
                                      bool tmp_table,
546
 
                                      uint32_t *db_options,
547
 
                                      KEY **key_info_buffer,
548
 
                                      uint32_t *key_count,
549
 
                                      int select_field_count)
 
918
/*
 
919
  Preparation for table creation
 
920
 
 
921
  SYNOPSIS
 
922
    mysql_prepare_create_table()
 
923
      session                       Thread object.
 
924
      create_info               Create information (like MAX_ROWS).
 
925
      alter_info                List of columns and indexes to create
 
926
      tmp_table                 If a temporary table is to be created.
 
927
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
 
928
      file                      The handler for the new table.
 
929
      key_info_buffer     OUT   An array of KEY structs for the indexes.
 
930
      key_count           OUT   The number of elements in the array.
 
931
      select_field_count        The number of fields coming from a select table.
 
932
 
 
933
  DESCRIPTION
 
934
    Prepares the table and key structures for table creation.
 
935
 
 
936
  NOTES
 
937
    sets create_info->varchar if the table has a varchar
 
938
 
 
939
  RETURN VALUES
 
940
    false    OK
 
941
    true     error
 
942
*/
 
943
 
 
944
static int
 
945
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
 
946
                           Alter_info *alter_info,
 
947
                           bool tmp_table,
 
948
                               uint32_t *db_options,
 
949
                               handler *file, KEY **key_info_buffer,
 
950
                               uint32_t *key_count, int select_field_count)
550
951
{
551
952
  const char    *key_name;
552
953
  CreateField   *sql_field,*dup_field;
561
962
  List_iterator<CreateField> it2(alter_info->create_list);
562
963
  uint32_t total_uneven_bit_length= 0;
563
964
 
564
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
565
 
 
566
965
  select_field_pos= alter_info->create_list.elements - select_field_count;
567
966
  null_fields=blob_columns=0;
568
 
  max_key_length= engine->max_key_length();
 
967
  create_info->varchar= 0;
 
968
  max_key_length= file->max_key_length();
569
969
 
570
970
  for (field_no=0; (sql_field=it++) ; field_no++)
571
971
  {
771
1171
        }
772
1172
      }
773
1173
    }
774
 
 
775
 
    /** @todo Get rid of this MyISAM-specific crap. */
776
 
    if (not create_proto.engine().name().compare("MyISAM") &&
777
 
        ((sql_field->flags & BLOB_FLAG) ||
778
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED)))
 
1174
    /* Don't pack rows in old tables if the user has requested this */
 
1175
    if ((sql_field->flags & BLOB_FLAG) ||
 
1176
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
779
1177
      (*db_options)|= HA_OPTION_PACK_RECORD;
780
1178
    it2.rewind();
781
1179
  }
790
1188
    assert(sql_field->charset != 0);
791
1189
 
792
1190
    if (prepare_create_field(sql_field, &blob_columns,
793
 
                             &timestamps, &timestamps_with_niladic))
 
1191
                             &timestamps, &timestamps_with_niladic,
 
1192
                             file->ha_table_flags()))
794
1193
      return(true);
 
1194
    if (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
 
1195
      create_info->varchar= true;
795
1196
    sql_field->offset= record_offset;
796
1197
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
797
1198
      auto_increment++;
808
1209
    return(true);
809
1210
  }
810
1211
  if (auto_increment &&
811
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1212
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
812
1213
  {
813
1214
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
814
1215
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
815
1216
    return(true);
816
1217
  }
817
1218
 
818
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1219
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
819
1220
  {
820
1221
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
821
1222
               MYF(0));
856
1257
      continue;
857
1258
    }
858
1259
    (*key_count)++;
859
 
    tmp= engine->max_key_parts();
 
1260
    tmp=file->max_key_parts();
860
1261
    if (key->columns.elements > tmp)
861
1262
    {
862
1263
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
905
1306
      return(true);
906
1307
    }
907
1308
  }
908
 
  tmp= engine->max_keys();
 
1309
  tmp=file->max_keys();
909
1310
  if (*key_count > tmp)
910
1311
  {
911
1312
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
912
1313
    return(true);
913
1314
  }
914
1315
 
915
 
  (*key_info_buffer)= key_info= (KEY*) memory::sql_calloc(sizeof(KEY) * (*key_count));
916
 
  key_part_info=(KEY_PART_INFO*) memory::sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
 
1316
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1317
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
917
1318
  if (!*key_info_buffer || ! key_part_info)
918
1319
    return(true);                               // Out of memory
919
1320
 
960
1361
    */
961
1362
    key_info->block_size= (key->key_create_info.block_size ?
962
1363
                           key->key_create_info.block_size :
963
 
                           create_proto.options().key_block_size());
 
1364
                           create_info->key_block_size);
964
1365
 
965
1366
    if (key_info->block_size)
966
1367
      key_info->flags|= HA_USES_BLOCK_SIZE;
986
1387
      key_info->comment.str= key->key_create_info.comment.str;
987
1388
    }
988
1389
 
989
 
    message::Table::Field *protofield= NULL;
990
 
 
991
1390
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
992
1391
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
993
1392
    {
994
1393
      uint32_t length;
995
1394
      Key_part_spec *dup_column;
996
 
      int proto_field_nr= 0;
997
1395
 
998
1396
      it.rewind();
999
1397
      field=0;
1000
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
1398
      while ((sql_field=it++) &&
1001
1399
             my_strcasecmp(system_charset_info,
1002
1400
                           column->field_name.str,
1003
1401
                           sql_field->field_name))
1010
1408
      while ((dup_column= cols2++) != column)
1011
1409
      {
1012
1410
        if (!my_strcasecmp(system_charset_info,
1013
 
                           column->field_name.str, dup_column->field_name.str))
 
1411
                           column->field_name.str, dup_column->field_name.str))
1014
1412
        {
1015
1413
          my_printf_error(ER_DUP_FIELDNAME,
1016
1414
                          ER(ER_DUP_FIELDNAME),MYF(0),
1019
1417
        }
1020
1418
      }
1021
1419
      cols2.rewind();
1022
 
 
1023
 
      if (create_proto.field_size() > 0)
1024
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1025
 
 
1026
1420
      {
1027
 
        column->length*= sql_field->charset->mbmaxlen;
 
1421
        column->length*= sql_field->charset->mbmaxlen;
1028
1422
 
1029
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1030
 
        {
1031
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1032
 
          {
1033
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1034
 
            return true;
1035
 
          }
1036
 
          if (! column->length)
1037
 
          {
1038
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
1039
 
            return true;
1040
 
          }
1041
 
        }
1042
 
        if (! (sql_field->flags & NOT_NULL_FLAG))
1043
 
        {
1044
 
          if (key->type == Key::PRIMARY)
1045
 
          {
1046
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1047
 
            sql_field->flags|= NOT_NULL_FLAG;
 
1423
        if (f_is_blob(sql_field->pack_flag))
 
1424
        {
 
1425
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
1426
          {
 
1427
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
1428
            return(true);
 
1429
          }
 
1430
          if (!column->length)
 
1431
          {
 
1432
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
1433
            return(true);
 
1434
          }
 
1435
        }
 
1436
        if (!(sql_field->flags & NOT_NULL_FLAG))
 
1437
        {
 
1438
          if (key->type == Key::PRIMARY)
 
1439
          {
 
1440
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
1441
            sql_field->flags|= NOT_NULL_FLAG;
 
1442
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1048
1443
            null_fields--;
1049
 
 
1050
 
            if (protofield)
1051
 
            {
1052
 
              message::Table::Field::FieldConstraints *constraints;
1053
 
              constraints= protofield->mutable_constraints();
1054
 
              constraints->set_is_nullable(false);
1055
 
            }
1056
 
 
1057
 
          }
1058
 
          else
 
1444
          }
 
1445
          else
1059
1446
          {
1060
1447
            key_info->flags|= HA_NULL_PART_KEY;
1061
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1448
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1062
1449
            {
1063
1450
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1064
 
              return true;
 
1451
              return(true);
1065
1452
            }
1066
1453
          }
1067
 
        }
1068
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1069
 
        {
1070
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1071
 
            auto_increment--;                   // Field is used
1072
 
        }
 
1454
        }
 
1455
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
1456
        {
 
1457
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
 
1458
            auto_increment--;                   // Field is used
 
1459
        }
1073
1460
      }
1074
1461
 
1075
1462
      key_part_info->fieldnr= field;
1079
1466
 
1080
1467
      if (column->length)
1081
1468
      {
1082
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
1469
        if (f_is_blob(sql_field->pack_flag))
1083
1470
        {
1084
1471
          if ((length=column->length) > max_key_length ||
1085
 
              length > engine->max_key_part_length())
 
1472
              length > file->max_key_part_length())
1086
1473
          {
1087
 
            length= min(max_key_length, engine->max_key_part_length());
 
1474
            length= min(max_key_length, file->max_key_part_length());
1088
1475
            if (key->type == Key::MULTIPLE)
1089
1476
            {
1090
1477
              /* not a critical problem */
1104
1491
          }
1105
1492
        }
1106
1493
        else if ((column->length > length ||
1107
 
            ! Field::type_can_have_key_part(sql_field->sql_type)))
 
1494
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
 
1495
                   ((f_is_packed(sql_field->pack_flag) ||
 
1496
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
 
1497
                      (key_info->flags & HA_NOSAME))) &&
 
1498
                    column->length != length)))
1108
1499
        {
1109
1500
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1110
1501
          return(true);
1111
1502
        }
1112
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1113
 
        {
 
1503
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1114
1504
          length=column->length;
1115
 
        }
1116
1505
      }
1117
1506
      else if (length == 0)
1118
1507
      {
1119
1508
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1120
1509
          return(true);
1121
1510
      }
1122
 
      if (length > engine->max_key_part_length())
 
1511
      if (length > file->max_key_part_length())
1123
1512
      {
1124
 
        length= engine->max_key_part_length();
 
1513
        length= file->max_key_part_length();
1125
1514
        if (key->type == Key::MULTIPLE)
1126
1515
        {
1127
1516
          /* not a critical problem */
1144
1533
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1145
1534
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1146
1535
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1147
 
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1536
            sql_field->pack_flag & FIELDFLAG_BLOB)))
1148
1537
      {
1149
 
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
 
1538
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1150
1539
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1151
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1152
 
        else
1153
 
          key_info->flags|= HA_PACK_KEY;
 
1540
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
1541
        else
 
1542
          key_info->flags|= HA_PACK_KEY;
1154
1543
      }
1155
1544
      /* Check if the key segment is partial, set the key flag accordingly */
1156
1545
      if (length != sql_field->key_length)
1201
1590
    key_info++;
1202
1591
  }
1203
1592
  if (!unique_key && !primary_key &&
1204
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1593
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1205
1594
  {
1206
1595
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1207
1596
    return(true);
1212
1601
    return(true);
1213
1602
  }
1214
1603
  /* Sort keys in optimized order */
1215
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1216
 
                     (qsort_cmp) sort_keys);
 
1604
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1605
           (qsort_cmp) sort_keys);
 
1606
  create_info->null_bits= null_fields;
1217
1607
 
1218
1608
  /* Check fields. */
1219
1609
  it.rewind();
1286
1676
  return 0;
1287
1677
}
1288
1678
 
1289
 
static bool locked_create_event(Session *session,
1290
 
                                TableIdentifier &identifier,
1291
 
                                HA_CREATE_INFO *create_info,
1292
 
                                message::Table &table_proto,
1293
 
                                AlterInfo *alter_info,
1294
 
                                bool is_if_not_exists,
1295
 
                                bool internal_tmp_table,
1296
 
                                uint db_options,
1297
 
                                uint key_count,
1298
 
                                KEY *key_info_buffer)
1299
 
{
1300
 
  bool error= true;
1301
 
 
1302
 
  {
1303
 
 
1304
 
    /*
1305
 
      @note if we are building a temp table we need to check to see if a temp table
1306
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1307
 
      to create a table under a temporary table.
1308
 
    */
1309
 
    bool exists= 
1310
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1311
 
                                            identifier.getType() != message::Table::STANDARD );
1312
 
 
1313
 
    if (exists)
1314
 
    {
1315
 
      if (is_if_not_exists)
1316
 
      {
1317
 
        error= false;
1318
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1319
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1320
 
                            identifier.getTableName().c_str());
1321
 
        create_info->table_existed= 1;          // Mark that table existed
1322
 
        return error;
1323
 
      }
1324
 
 
1325
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1326
 
      return error;
1327
 
    }
1328
 
 
1329
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1330
 
    {
1331
 
      /*
1332
 
        We don't assert here, but check the result, because the table could be
1333
 
        in the table definition cache and in the same time the .frm could be
1334
 
        missing from the disk, in case of manual intervention which deletes
1335
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1336
 
        Then she could create the table. This case is pretty obscure and
1337
 
        therefore we don't introduce a new error message only for it.
1338
 
      */
1339
 
      /*
1340
 
        @todo improve this error condition.
1341
 
      */
1342
 
      if (TableShare::getShare(identifier))
1343
 
      {
1344
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1345
 
        return error;
1346
 
      }
1347
 
    }
1348
 
  }
1349
 
 
1350
 
  session->set_proc_info("creating table");
1351
 
  create_info->table_existed= 0;                // Mark that table is created
1352
 
 
1353
 
  create_info->table_options= db_options;
1354
 
 
1355
 
  if (not rea_create_table(session, identifier,
1356
 
                           table_proto,
1357
 
                           create_info, alter_info->create_list,
1358
 
                           key_count, key_info_buffer))
1359
 
  {
1360
 
    return error;
1361
 
  }
1362
 
 
1363
 
  if (identifier.getType() == message::Table::TEMPORARY)
1364
 
  {
1365
 
    /* Open table and put in temporary table list */
1366
 
    if (not (session->open_temporary_table(identifier)))
1367
 
    {
1368
 
      (void) session->rm_temporary_table(identifier);
1369
 
      return error;
1370
 
    }
1371
 
  }
1372
 
 
1373
 
  /* 
1374
 
    We keep this behind the lock to make sure ordering is correct for a table.
1375
 
    This is a very unlikely problem where before we would write out to the
1376
 
    trans log, someone would do a delete/create operation.
1377
 
  */
1378
 
 
1379
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1380
 
  {
1381
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1382
 
    transaction_services.createTable(session, table_proto);
1383
 
  }
1384
 
 
1385
 
  return false;
1386
 
}
1387
 
 
1388
1679
 
1389
1680
/*
1390
1681
  Ignore the name of this function... it locks :(
1417
1708
*/
1418
1709
 
1419
1710
bool mysql_create_table_no_lock(Session *session,
1420
 
                                TableIdentifier &identifier,
 
1711
                                const char *db, const char *table_name,
1421
1712
                                HA_CREATE_INFO *create_info,
1422
 
                                message::Table &table_proto,
1423
 
                                AlterInfo *alter_info,
 
1713
                                drizzled::message::Table *table_proto,
 
1714
                                Alter_info *alter_info,
1424
1715
                                bool internal_tmp_table,
1425
 
                                uint32_t select_field_count,
1426
 
                                bool is_if_not_exists)
 
1716
                                uint32_t select_field_count)
1427
1717
{
 
1718
  char          path[FN_REFLEN];
 
1719
  uint32_t          path_length;
1428
1720
  uint          db_options, key_count;
1429
1721
  KEY           *key_info_buffer;
 
1722
  handler       *file;
1430
1723
  bool          error= true;
1431
 
  TableShare share;
1432
 
 
1433
1724
  /* Check for duplicate fields and check type of table to create */
1434
 
  if (not alter_info->create_list.elements)
 
1725
  if (!alter_info->create_list.elements)
1435
1726
  {
1436
1727
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1437
1728
               MYF(0));
1438
1729
    return true;
1439
1730
  }
1440
 
  assert(identifier.getTableName() == table_proto.name());
 
1731
  assert(strcmp(table_name,table_proto->name().c_str())==0);
 
1732
  if (check_engine(session, table_name, create_info))
 
1733
    return true;
1441
1734
  db_options= create_info->table_options;
1442
 
 
1443
1735
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
1444
1736
    db_options|=HA_OPTION_PACK_RECORD;
1445
 
 
1446
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1447
 
 
1448
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1449
 
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1737
  if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
 
1738
                              create_info->db_type)))
 
1739
  {
 
1740
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
1741
    return true;
 
1742
  }
 
1743
 
 
1744
  set_table_default_charset(create_info, (char*) db);
 
1745
 
 
1746
  if (mysql_prepare_create_table(session, create_info, alter_info,
1450
1747
                                 internal_tmp_table,
1451
 
                                 &db_options,
 
1748
                                 &db_options, file,
1452
1749
                                 &key_info_buffer, &key_count,
1453
1750
                                 select_field_count))
1454
 
  {
1455
 
    pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1456
 
    error= locked_create_event(session,
1457
 
                               identifier,
1458
 
                               create_info,
1459
 
                               table_proto,
1460
 
                               alter_info,
1461
 
                               is_if_not_exists,
1462
 
                               internal_tmp_table,
1463
 
                               db_options, key_count,
1464
 
                               key_info_buffer);
1465
 
    pthread_mutex_unlock(&LOCK_open);
1466
 
  }
1467
 
 
 
1751
    goto err;
 
1752
 
 
1753
      /* Check if table exists */
 
1754
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1755
  {
 
1756
    path_length= build_tmptable_filename(session, path, sizeof(path));
 
1757
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
1758
  }
 
1759
  else
 
1760
  {
 
1761
 #ifdef FN_DEVCHAR
 
1762
    /* check if the table name contains FN_DEVCHAR when defined */
 
1763
    if (strchr(table_name, FN_DEVCHAR))
 
1764
    {
 
1765
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
 
1766
      return true;
 
1767
    }
 
1768
#endif
 
1769
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
 
1770
  }
 
1771
 
 
1772
  /* Check if table already exists */
 
1773
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1774
      session->find_temporary_table(db, table_name))
 
1775
  {
 
1776
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1777
    {
 
1778
      create_info->table_existed= 1;            // Mark that table existed
 
1779
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1780
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1781
                          table_name);
 
1782
      error= 0;
 
1783
      goto err;
 
1784
    }
 
1785
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1786
    goto err;
 
1787
  }
 
1788
 
 
1789
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1790
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1791
  {
 
1792
    if (StorageEngine::getTableProto(path, NULL)==EEXIST)
 
1793
    {
 
1794
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1795
      {
 
1796
        error= false;
 
1797
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1798
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1799
                            table_name);
 
1800
        create_info->table_existed= 1;          // Mark that table existed
 
1801
      }
 
1802
      else 
 
1803
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1804
 
 
1805
      goto unlock_and_end;
 
1806
    }
 
1807
    /*
 
1808
      We don't assert here, but check the result, because the table could be
 
1809
      in the table definition cache and in the same time the .frm could be
 
1810
      missing from the disk, in case of manual intervention which deletes
 
1811
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1812
      Then she could create the table. This case is pretty obscure and
 
1813
      therefore we don't introduce a new error message only for it.
 
1814
    */
 
1815
    if (TableShare::getShare(db, table_name))
 
1816
    {
 
1817
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1818
      goto unlock_and_end;
 
1819
    }
 
1820
  }
 
1821
 
 
1822
  /*
 
1823
    Check that table with given name does not already
 
1824
    exist in any storage engine. In such a case it should
 
1825
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1826
    unless user specified CREATE TABLE IF EXISTS
 
1827
    The LOCK_open mutex has been locked to make sure no
 
1828
    one else is attempting to discover the table. Since
 
1829
    it's not on disk as a frm file, no one could be using it!
 
1830
  */
 
1831
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1832
  {
 
1833
    bool create_if_not_exists =
 
1834
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1835
 
 
1836
    char table_path[FN_REFLEN];
 
1837
    uint32_t          table_path_length;
 
1838
 
 
1839
    table_path_length= build_table_filename(table_path, sizeof(table_path),
 
1840
                                            db, table_name, false);
 
1841
 
 
1842
    int retcode= StorageEngine::getTableProto(table_path, NULL);
 
1843
    switch (retcode)
 
1844
    {
 
1845
      case ENOENT:
 
1846
        /* Normal case, no table exists. we can go and create it */
 
1847
        break;
 
1848
      case EEXIST:
 
1849
        if (create_if_not_exists)
 
1850
        {
 
1851
          error= false;
 
1852
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1853
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1854
                              table_name);
 
1855
          create_info->table_existed= 1;                // Mark that table existed
 
1856
          goto unlock_and_end;
 
1857
        }
 
1858
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1859
        goto unlock_and_end;
 
1860
      default:
 
1861
        my_error(retcode, MYF(0),table_name);
 
1862
        goto unlock_and_end;
 
1863
    }
 
1864
  }
 
1865
 
 
1866
  session->set_proc_info("creating table");
 
1867
  create_info->table_existed= 0;                // Mark that table is created
 
1868
 
 
1869
#ifdef HAVE_READLINK
 
1870
  if (test_if_data_home_dir(create_info->data_file_name))
 
1871
  {
 
1872
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
 
1873
    goto unlock_and_end;
 
1874
  }
 
1875
  if (test_if_data_home_dir(create_info->index_file_name))
 
1876
  {
 
1877
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
 
1878
    goto unlock_and_end;
 
1879
  }
 
1880
 
 
1881
  if (!my_use_symdir)
 
1882
#endif /* HAVE_READLINK */
 
1883
  {
 
1884
    if (create_info->data_file_name)
 
1885
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1886
                   "DATA DIRECTORY option ignored");
 
1887
    if (create_info->index_file_name)
 
1888
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1889
                   "INDEX DIRECTORY option ignored");
 
1890
    create_info->data_file_name= create_info->index_file_name= 0;
 
1891
  }
 
1892
  create_info->table_options=db_options;
 
1893
 
 
1894
  if (rea_create_table(session, path, db, table_name,
 
1895
                       table_proto,
 
1896
                       create_info, alter_info->create_list,
 
1897
                       key_count, key_info_buffer))
 
1898
    goto unlock_and_end;
 
1899
 
 
1900
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1901
  {
 
1902
    /* Open table and put in temporary table list */
 
1903
    if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
 
1904
    {
 
1905
      (void) session->rm_temporary_table(create_info->db_type, path);
 
1906
      goto unlock_and_end;
 
1907
    }
 
1908
  }
 
1909
 
 
1910
  /*
 
1911
    Don't write statement if:
 
1912
    - It is an internal temporary table,
 
1913
    - Row-based logging is used and it we are creating a temporary table, or
 
1914
    - The binary log is not open.
 
1915
    Otherwise, the statement shall be binlogged.
 
1916
   */
 
1917
  if (!internal_tmp_table &&
 
1918
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1919
    write_bin_log(session, true, session->query, session->query_length);
 
1920
  error= false;
 
1921
unlock_and_end:
 
1922
  pthread_mutex_unlock(&LOCK_open);
 
1923
 
 
1924
err:
1468
1925
  session->set_proc_info("After create");
1469
 
 
 
1926
  delete file;
1470
1927
  return(error);
1471
1928
}
1472
1929
 
1473
 
/**
1474
 
  @note the following two methods implement create [temporary] table.
 
1930
 
 
1931
/*
 
1932
  Database locking aware wrapper for mysql_create_table_no_lock(),
1475
1933
*/
1476
 
static bool drizzle_create_table(Session *session,
1477
 
                                 TableIdentifier &identifier,
1478
 
                                 HA_CREATE_INFO *create_info,
1479
 
                                 message::Table &table_proto,
1480
 
                                 AlterInfo *alter_info,
1481
 
                                 bool internal_tmp_table,
1482
 
                                 uint32_t select_field_count,
1483
 
                                 bool is_if_not_exists)
 
1934
 
 
1935
bool mysql_create_table(Session *session, const char *db, const char *table_name,
 
1936
                        HA_CREATE_INFO *create_info,
 
1937
                        drizzled::message::Table *table_proto,
 
1938
                        Alter_info *alter_info,
 
1939
                        bool internal_tmp_table,
 
1940
                        uint32_t select_field_count)
1484
1941
{
1485
1942
  Table *name_lock= NULL;
1486
1943
  bool result;
1487
1944
 
1488
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1489
 
  {
1490
 
    result= true;
1491
 
  }
1492
 
  else if (name_lock == NULL)
1493
 
  {
1494
 
    if (is_if_not_exists)
1495
 
    {
1496
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1497
 
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1498
 
                          identifier.getTableName().c_str());
1499
 
      create_info->table_existed= 1;
1500
 
      result= false;
1501
 
    }
1502
 
    else
1503
 
    {
1504
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
 
1945
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1946
  {
 
1947
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
1948
    {
1505
1949
      result= true;
1506
 
    }
1507
 
  }
1508
 
  else
1509
 
  {
1510
 
    result= mysql_create_table_no_lock(session,
1511
 
                                       identifier,
1512
 
                                       create_info,
1513
 
                                       table_proto,
1514
 
                                       alter_info,
1515
 
                                       internal_tmp_table,
1516
 
                                       select_field_count,
1517
 
                                       is_if_not_exists);
1518
 
  }
1519
 
 
 
1950
      goto unlock;
 
1951
    }
 
1952
    if (name_lock == NULL)
 
1953
    {
 
1954
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1955
      {
 
1956
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1957
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1958
                            table_name);
 
1959
        create_info->table_existed= 1;
 
1960
        result= false;
 
1961
      }
 
1962
      else
 
1963
      {
 
1964
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1965
        result= true;
 
1966
      }
 
1967
      goto unlock;
 
1968
    }
 
1969
  }
 
1970
 
 
1971
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1972
                                     table_proto,
 
1973
                                     alter_info,
 
1974
                                     internal_tmp_table,
 
1975
                                     select_field_count);
 
1976
 
 
1977
unlock:
1520
1978
  if (name_lock)
1521
1979
  {
1522
1980
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1529
1987
 
1530
1988
 
1531
1989
/*
1532
 
  Database locking aware wrapper for mysql_create_table_no_lock(),
1533
 
*/
1534
 
bool mysql_create_table(Session *session,
1535
 
                        TableIdentifier &identifier,
1536
 
                        HA_CREATE_INFO *create_info,
1537
 
                        message::Table &table_proto,
1538
 
                        AlterInfo *alter_info,
1539
 
                        bool internal_tmp_table,
1540
 
                        uint32_t select_field_count,
1541
 
                        bool is_if_not_exists)
1542
 
{
1543
 
  if (identifier.isTmp())
1544
 
  {
1545
 
    return mysql_create_table_no_lock(session,
1546
 
                                      identifier,
1547
 
                                      create_info,
1548
 
                                      table_proto,
1549
 
                                      alter_info,
1550
 
                                      internal_tmp_table,
1551
 
                                      select_field_count,
1552
 
                                      is_if_not_exists);
1553
 
  }
1554
 
 
1555
 
  return drizzle_create_table(session,
1556
 
                              identifier,
1557
 
                              create_info,
1558
 
                              table_proto,
1559
 
                              alter_info,
1560
 
                              internal_tmp_table,
1561
 
                              select_field_count,
1562
 
                              is_if_not_exists);
1563
 
}
1564
 
 
1565
 
 
1566
 
/*
1567
1990
** Give the key name after the first field with an optional '_#' after
1568
1991
**/
1569
1992
 
1596
2019
  for (uint32_t i=2 ; i< 100; i++)
1597
2020
  {
1598
2021
    *buff_end= '_';
1599
 
    internal::int10_to_str(i, buff_end+1, 10);
 
2022
    int10_to_str(i, buff_end+1, 10);
1600
2023
    if (!check_if_keyname_exists(buff,start,end))
1601
 
      return memory::sql_strdup(buff);
 
2024
      return sql_strdup(buff);
1602
2025
  }
1603
2026
  return (char*) "not_specified";               // Should never happen
1604
2027
}
1608
2031
** Alter a table definition
1609
2032
****************************************************************************/
1610
2033
 
 
2034
 
1611
2035
/*
1612
2036
  Rename a table.
1613
2037
 
1614
2038
  SYNOPSIS
1615
2039
    mysql_rename_table()
1616
 
      base                      The plugin::StorageEngine handle.
 
2040
      base                      The StorageEngine handle.
1617
2041
      old_db                    The old database name.
1618
2042
      old_name                  The old table name.
1619
2043
      new_db                    The new database name.
1621
2045
      flags                     flags for build_table_filename().
1622
2046
                                FN_FROM_IS_TMP old_name is temporary.
1623
2047
                                FN_TO_IS_TMP   new_name is temporary.
 
2048
                                NO_FRM_RENAME  Don't rename the FRM file
 
2049
                                but only the table in the storage engine.
1624
2050
 
1625
2051
  RETURN
1626
2052
    false   OK
1628
2054
*/
1629
2055
 
1630
2056
bool
1631
 
mysql_rename_table(plugin::StorageEngine *base,
1632
 
                   TableIdentifier &from,
1633
 
                   TableIdentifier &to,
1634
 
                   uint32_t )
 
2057
mysql_rename_table(StorageEngine *base, const char *old_db,
 
2058
                   const char *old_name, const char *new_db,
 
2059
                   const char *new_name, uint32_t flags)
1635
2060
{
1636
2061
  Session *session= current_session;
 
2062
  char from[FN_REFLEN], to[FN_REFLEN];
 
2063
  char *from_base= from, *to_base= to;
1637
2064
  int error= 0;
1638
2065
 
1639
2066
  assert(base);
1640
2067
 
1641
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
2068
  build_table_filename(from, sizeof(from), old_db, old_name,
 
2069
                       flags & FN_FROM_IS_TMP);
 
2070
  build_table_filename(to, sizeof(to), new_db, new_name,
 
2071
                       flags & FN_TO_IS_TMP);
 
2072
 
 
2073
  if (!(error=base->renameTable(session, from_base, to_base)))
1642
2074
  {
1643
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1644
 
    return true;
 
2075
    if(!(flags & NO_FRM_RENAME)
 
2076
       && base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
2077
       && rename_table_proto_file(from_base, to_base))
 
2078
    {
 
2079
      error= my_errno;
 
2080
      base->renameTable(session, to_base, from_base);
 
2081
    }
1645
2082
  }
1646
2083
 
1647
 
  error= base->renameTable(*session, from, to);
1648
 
 
1649
2084
  if (error == HA_ERR_WRONG_COMMAND)
1650
 
  {
1651
2085
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1652
 
  }
1653
2086
  else if (error)
1654
 
  {
1655
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str();
1656
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str();
1657
 
 
1658
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1659
 
  }
1660
 
 
1661
 
  return error ? true : false; 
 
2087
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
2088
  return(error != 0);
1662
2089
}
1663
2090
 
1664
2091
 
1667
2094
 
1668
2095
  SYNOPSIS
1669
2096
    wait_while_table_is_used()
1670
 
    session                     Thread Cursor
 
2097
    session                     Thread handler
1671
2098
    table               Table to remove from cache
1672
2099
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1673
2100
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1687
2114
 
1688
2115
  safe_mutex_assert_owner(&LOCK_open);
1689
2116
 
1690
 
  table->cursor->extra(function);
 
2117
  table->file->extra(function);
1691
2118
  /* Mark all tables that are in use as 'old' */
1692
 
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
 
2119
  mysql_lock_abort(session, table, true);       /* end threads waiting on lock */
1693
2120
 
1694
2121
  /* Wait until all there are no other threads that has this table open */
1695
 
  remove_table_from_cache(session, table->s->getSchemaName(),
 
2122
  remove_table_from_cache(session, table->s->db.str,
1696
2123
                          table->s->table_name.str,
1697
2124
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1698
2125
}
1702
2129
 
1703
2130
  SYNOPSIS
1704
2131
    close_cached_table()
1705
 
    session                     Thread Cursor
 
2132
    session                     Thread handler
1706
2133
    table               Table to remove from cache
1707
2134
 
1708
2135
  NOTES
1742
2169
                              const char *operator_name,
1743
2170
                              thr_lock_type lock_type,
1744
2171
                              bool open_for_modify,
1745
 
                              int (Cursor::*operator_func)(Session *,
 
2172
                              bool no_warnings_for_error,
 
2173
                              uint32_t extra_open_options,
 
2174
                              int (*prepare_func)(Session *, TableList *,
 
2175
                                                  HA_CHECK_OPT *),
 
2176
                              int (handler::*operator_func)(Session *,
1746
2177
                                                            HA_CHECK_OPT *))
1747
2178
{
1748
2179
  TableList *table;
1749
2180
  Select_Lex *select= &session->lex->select_lex;
1750
2181
  List<Item> field_list;
1751
2182
  Item *item;
 
2183
  Protocol *protocol= session->protocol;
1752
2184
  LEX *lex= session->lex;
1753
2185
  int result_code= 0;
1754
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1755
2186
  const CHARSET_INFO * const cs= system_charset_info;
1756
2187
 
1757
2188
  if (! session->endActiveTransaction())
1766
2197
  item->maybe_null = 1;
1767
2198
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1768
2199
  item->maybe_null = 1;
1769
 
  if (session->client->sendFields(&field_list))
1770
 
    return true;
 
2200
  if (protocol->sendFields(&field_list,
 
2201
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
2202
    return(true);
1771
2203
 
1772
2204
  for (table= tables; table; table= table->next_local)
1773
2205
  {
1775
2207
    char* db = table->db;
1776
2208
    bool fatal_error=0;
1777
2209
 
1778
 
    snprintf(table_name, sizeof(table_name), "%s.%s",db,table->table_name);
 
2210
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2211
    session->open_options|= extra_open_options;
1779
2212
    table->lock_type= lock_type;
1780
2213
    /* open only one table from local list of command */
1781
2214
    {
1794
2227
      lex->query_tables= table;
1795
2228
      lex->query_tables_last= &table->next_global;
1796
2229
      lex->query_tables_own_last= 0;
1797
 
      session->no_warnings_for_error= 0;
 
2230
      session->no_warnings_for_error= no_warnings_for_error;
1798
2231
 
1799
2232
      session->openTablesLock(table);
1800
2233
      session->no_warnings_for_error= 0;
1801
2234
      table->next_global= save_next_global;
1802
2235
      table->next_local= save_next_local;
 
2236
      session->open_options&= ~extra_open_options;
 
2237
    }
 
2238
 
 
2239
    if (prepare_func)
 
2240
    {
 
2241
      switch ((*prepare_func)(session, table, check_opt)) {
 
2242
      case  1:           // error, message written to net
 
2243
        ha_autocommit_or_rollback(session, 1);
 
2244
        session->endTransaction(ROLLBACK);
 
2245
        session->close_thread_tables();
 
2246
        continue;
 
2247
      case -1:           // error, message could be written to net
 
2248
        /* purecov: begin inspected */
 
2249
        goto err;
 
2250
        /* purecov: end */
 
2251
      default:           // should be 0 otherwise
 
2252
        ;
 
2253
      }
1803
2254
    }
1804
2255
 
1805
2256
    /*
1821
2272
 
1822
2273
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
1823
2274
    {
 
2275
      /* purecov: begin inspected */
1824
2276
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1825
2277
      uint32_t length;
1826
 
      session->client->store(table_name);
1827
 
      session->client->store(operator_name);
1828
 
      session->client->store(STRING_WITH_LEN("error"));
 
2278
      protocol->prepareForResend();
 
2279
      protocol->store(table_name);
 
2280
      protocol->store(operator_name);
 
2281
      protocol->store(STRING_WITH_LEN("error"));
1829
2282
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1830
2283
                       table_name);
1831
 
      session->client->store(buff, length);
1832
 
      transaction_services.ha_autocommit_or_rollback(session, false);
 
2284
      protocol->store(buff, length);
 
2285
      ha_autocommit_or_rollback(session, 0);
1833
2286
      session->endTransaction(COMMIT);
1834
2287
      session->close_thread_tables();
1835
2288
      lex->reset_query_tables_list(false);
1836
2289
      table->table=0;                           // For query cache
1837
 
      if (session->client->flush())
 
2290
      if (protocol->write())
1838
2291
        goto err;
1839
2292
      continue;
 
2293
      /* purecov: end */
1840
2294
    }
1841
2295
 
1842
2296
    /* Close all instances of the table to allow repair to rename files */
1845
2299
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
1846
2300
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1847
2301
                                              "Waiting to get writelock");
1848
 
      mysql_lock_abort(session,table->table);
1849
 
      remove_table_from_cache(session, table->table->s->getSchemaName(),
 
2302
      mysql_lock_abort(session,table->table, true);
 
2303
      remove_table_from_cache(session, table->table->s->db.str,
1850
2304
                              table->table->s->table_name.str,
1851
2305
                              RTFC_WAIT_OTHER_THREAD_FLAG |
1852
2306
                              RTFC_CHECK_KILLED_FLAG);
1856
2310
      open_for_modify= 0;
1857
2311
    }
1858
2312
 
1859
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
2313
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2314
    {
 
2315
      /* purecov: begin inspected */
 
2316
      protocol->prepareForResend();
 
2317
      protocol->store(table_name);
 
2318
      protocol->store(operator_name);
 
2319
      protocol->store(STRING_WITH_LEN("warning"));
 
2320
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2321
      if (protocol->write())
 
2322
        goto err;
 
2323
      /* purecov: end */
 
2324
    }
 
2325
 
 
2326
    result_code = (table->table->file->*operator_func)(session, check_opt);
1860
2327
 
1861
2328
send_result:
1862
2329
 
1867
2334
      DRIZZLE_ERROR *err;
1868
2335
      while ((err= it++))
1869
2336
      {
1870
 
        session->client->store(table_name);
1871
 
        session->client->store(operator_name);
1872
 
        session->client->store(warning_level_names[err->level].str,
1873
 
                               warning_level_names[err->level].length);
1874
 
        session->client->store(err->msg);
1875
 
        if (session->client->flush())
 
2337
        protocol->prepareForResend();
 
2338
        protocol->store(table_name);
 
2339
        protocol->store(operator_name);
 
2340
        protocol->store(warning_level_names[err->level].str,
 
2341
                        warning_level_names[err->level].length);
 
2342
        protocol->store(err->msg);
 
2343
        if (protocol->write())
1876
2344
          goto err;
1877
2345
      }
1878
2346
      drizzle_reset_errors(session, true);
1879
2347
    }
1880
 
    session->client->store(table_name);
1881
 
    session->client->store(operator_name);
 
2348
    protocol->prepareForResend();
 
2349
    protocol->store(table_name);
 
2350
    protocol->store(operator_name);
 
2351
 
 
2352
send_result_message:
1882
2353
 
1883
2354
    switch (result_code) {
1884
2355
    case HA_ADMIN_NOT_IMPLEMENTED:
1886
2357
        char buf[ERRMSGSIZE+20];
1887
2358
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1888
2359
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1889
 
        session->client->store(STRING_WITH_LEN("note"));
1890
 
        session->client->store(buf, length);
 
2360
        protocol->store(STRING_WITH_LEN("note"));
 
2361
        protocol->store(buf, length);
1891
2362
      }
1892
2363
      break;
1893
2364
 
1894
2365
    case HA_ADMIN_OK:
1895
 
      session->client->store(STRING_WITH_LEN("status"));
1896
 
      session->client->store(STRING_WITH_LEN("OK"));
 
2366
      protocol->store(STRING_WITH_LEN("status"));
 
2367
      protocol->store(STRING_WITH_LEN("OK"));
1897
2368
      break;
1898
2369
 
1899
2370
    case HA_ADMIN_FAILED:
1900
 
      session->client->store(STRING_WITH_LEN("status"));
1901
 
      session->client->store(STRING_WITH_LEN("Operation failed"));
 
2371
      protocol->store(STRING_WITH_LEN("status"));
 
2372
      protocol->store(STRING_WITH_LEN("Operation failed"));
1902
2373
      break;
1903
2374
 
1904
2375
    case HA_ADMIN_REJECT:
1905
 
      session->client->store(STRING_WITH_LEN("status"));
1906
 
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
 
2376
      protocol->store(STRING_WITH_LEN("status"));
 
2377
      protocol->store(STRING_WITH_LEN("Operation need committed state"));
1907
2378
      open_for_modify= false;
1908
2379
      break;
1909
2380
 
1910
2381
    case HA_ADMIN_ALREADY_DONE:
1911
 
      session->client->store(STRING_WITH_LEN("status"));
1912
 
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
 
2382
      protocol->store(STRING_WITH_LEN("status"));
 
2383
      protocol->store(STRING_WITH_LEN("Table is already up to date"));
1913
2384
      break;
1914
2385
 
1915
2386
    case HA_ADMIN_CORRUPT:
1916
 
      session->client->store(STRING_WITH_LEN("error"));
1917
 
      session->client->store(STRING_WITH_LEN("Corrupt"));
 
2387
      protocol->store(STRING_WITH_LEN("error"));
 
2388
      protocol->store(STRING_WITH_LEN("Corrupt"));
1918
2389
      fatal_error=1;
1919
2390
      break;
1920
2391
 
1921
2392
    case HA_ADMIN_INVALID:
1922
 
      session->client->store(STRING_WITH_LEN("error"));
1923
 
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1924
 
      break;
 
2393
      protocol->store(STRING_WITH_LEN("error"));
 
2394
      protocol->store(STRING_WITH_LEN("Invalid argument"));
 
2395
      break;
 
2396
 
 
2397
    case HA_ADMIN_TRY_ALTER:
 
2398
    {
 
2399
      /*
 
2400
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2401
        "try with alter", so here we close the table, do an ALTER Table,
 
2402
        reopen the table and do ha_innobase::analyze() on it.
 
2403
      */
 
2404
      ha_autocommit_or_rollback(session, 0);
 
2405
      session->close_thread_tables();
 
2406
      TableList *save_next_local= table->next_local,
 
2407
                 *save_next_global= table->next_global;
 
2408
      table->next_local= table->next_global= 0;
 
2409
      result_code= mysql_recreate_table(session, table);
 
2410
      /*
 
2411
        mysql_recreate_table() can push OK or ERROR.
 
2412
        Clear 'OK' status. If there is an error, keep it:
 
2413
        we will store the error message in a result set row
 
2414
        and then clear.
 
2415
      */
 
2416
      if (session->main_da.is_ok())
 
2417
        session->main_da.reset_diagnostics_area();
 
2418
      ha_autocommit_or_rollback(session, 0);
 
2419
      session->close_thread_tables();
 
2420
      if (!result_code) // recreation went ok
 
2421
      {
 
2422
        if ((table->table= session->openTableLock(table, lock_type)) &&
 
2423
            ((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
 
2424
          result_code= 0; // analyze went ok
 
2425
      }
 
2426
      if (result_code) // either mysql_recreate_table or analyze failed
 
2427
      {
 
2428
        assert(session->is_error());
 
2429
        if (session->is_error())
 
2430
        {
 
2431
          const char *err_msg= session->main_da.message();
 
2432
          if (!session->protocol->isConnected())
 
2433
          {
 
2434
            errmsg_printf(ERRMSG_LVL_ERROR, "%s", err_msg);
 
2435
          }
 
2436
          else
 
2437
          {
 
2438
            /* Hijack the row already in-progress. */
 
2439
            protocol->store(STRING_WITH_LEN("error"));
 
2440
            protocol->store(err_msg);
 
2441
            (void)protocol->write();
 
2442
            /* Start off another row for HA_ADMIN_FAILED */
 
2443
            protocol->prepareForResend();
 
2444
            protocol->store(table_name);
 
2445
            protocol->store(operator_name);
 
2446
          }
 
2447
          session->clear_error();
 
2448
        }
 
2449
      }
 
2450
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2451
      table->next_local= save_next_local;
 
2452
      table->next_global= save_next_global;
 
2453
      goto send_result_message;
 
2454
    }
 
2455
    case HA_ADMIN_NEEDS_UPGRADE:
 
2456
    case HA_ADMIN_NEEDS_ALTER:
 
2457
    {
 
2458
      char buf[ERRMSGSIZE];
 
2459
      uint32_t length;
 
2460
 
 
2461
      protocol->store(STRING_WITH_LEN("error"));
 
2462
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2463
      protocol->store(buf, length);
 
2464
      fatal_error=1;
 
2465
      break;
 
2466
    }
1925
2467
 
1926
2468
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1927
2469
      {
1929
2471
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1930
2472
                             _("Unknown - internal error %d during operation"),
1931
2473
                             result_code);
1932
 
        session->client->store(STRING_WITH_LEN("error"));
1933
 
        session->client->store(buf, length);
 
2474
        protocol->store(STRING_WITH_LEN("error"));
 
2475
        protocol->store(buf, length);
1934
2476
        fatal_error=1;
1935
2477
        break;
1936
2478
      }
1942
2484
      else if (open_for_modify)
1943
2485
      {
1944
2486
        if (table->table->s->tmp_table)
1945
 
          table->table->cursor->info(HA_STATUS_CONST);
 
2487
          table->table->file->info(HA_STATUS_CONST);
1946
2488
        else
1947
2489
        {
1948
2490
          pthread_mutex_lock(&LOCK_open);
1949
 
          remove_table_from_cache(session, table->table->s->getSchemaName(),
 
2491
          remove_table_from_cache(session, table->table->s->db.str,
1950
2492
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
1951
2493
          pthread_mutex_unlock(&LOCK_open);
1952
2494
        }
1953
2495
      }
1954
2496
    }
1955
 
    transaction_services.ha_autocommit_or_rollback(session, false);
 
2497
    ha_autocommit_or_rollback(session, 0);
1956
2498
    session->endTransaction(COMMIT);
1957
2499
    session->close_thread_tables();
1958
2500
    table->table=0;                             // For query cache
1959
 
    if (session->client->flush())
 
2501
    if (protocol->write())
1960
2502
      goto err;
1961
2503
  }
1962
2504
 
1964
2506
  return(false);
1965
2507
 
1966
2508
err:
1967
 
  transaction_services.ha_autocommit_or_rollback(session, true);
 
2509
  ha_autocommit_or_rollback(session, 1);
1968
2510
  session->endTransaction(ROLLBACK);
1969
2511
  session->close_thread_tables();                       // Shouldn't be needed
1970
2512
  if (table)
1972
2514
  return(true);
1973
2515
}
1974
2516
 
1975
 
/*
1976
 
  We have to write the query before we unlock the named table.
1977
 
 
1978
 
  Since temporary tables are not replicated under row-based
1979
 
  replication, CREATE TABLE ... LIKE ... needs special
1980
 
  treatement.  We have four cases to consider, according to the
1981
 
  following decision table:
1982
 
 
1983
 
  ==== ========= ========= ==============================
1984
 
  Case    Target    Source Write to binary log
1985
 
  ==== ========= ========= ==============================
1986
 
  1       normal    normal Original statement
1987
 
  2       normal temporary Generated statement
1988
 
  3    temporary    normal Nothing
1989
 
  4    temporary temporary Nothing
1990
 
  ==== ========= ========= ==============================
1991
 
*/
1992
 
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
1993
 
                                     bool is_src_table_tmp, bool is_if_not_exists)
 
2517
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
1994
2518
{
1995
 
  if (is_src_table_tmp)
1996
 
  {
1997
 
    char buf[2048];
1998
 
    String query(buf, sizeof(buf), system_charset_info);
1999
 
    query.length(0);  // Have to zero it since constructor doesn't
2000
 
 
2001
 
 
2002
 
    /*
2003
 
      Here we open the destination table, on which we already have
2004
 
      name-lock. This is needed for store_create_info() to work.
2005
 
      The table will be closed by unlink_open_table() at the end
2006
 
      of this function.
2007
 
    */
2008
 
    table->table= name_lock;
2009
 
    pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2010
 
    if (session->reopen_name_locked_table(table, false))
2011
 
    {
2012
 
      pthread_mutex_unlock(&LOCK_open);
2013
 
      return false;
2014
 
    }
2015
 
    pthread_mutex_unlock(&LOCK_open);
2016
 
 
2017
 
    int result= store_create_info(table, &query, is_if_not_exists);
2018
 
 
2019
 
    assert(result == 0); // store_create_info() always return 0
2020
 
    write_bin_log(session, query.ptr());
2021
 
  }
2022
 
  else                                      // Case 1
2023
 
  {
2024
 
    write_bin_log(session, session->query.c_str());
2025
 
  }
2026
 
 
2027
 
  return true;
 
2519
  return(mysql_admin_table(session, tables, check_opt,
 
2520
                           "optimize", TL_WRITE, 1,0,0,0,
 
2521
                           &handler::ha_optimize));
2028
2522
}
2029
2523
 
2030
 
  /*
2031
 
    Create a new table by copying from source table
2032
 
 
2033
 
    Altough exclusive name-lock on target table protects us from concurrent
2034
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
2035
 
    to plugin::StorageEngine::createTable() in critical section protected by
2036
 
    LOCK_open in order to provide minimal atomicity against operations which
2037
 
    disregard name-locks, like I_S implementation, for example. This is a
2038
 
    temporary and should not be copied. Instead we should fix our code to
2039
 
    always honor name-locks.
2040
 
 
2041
 
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2042
 
    during the call to plugin::StorageEngine::createTable().
2043
 
    See bug #28614 for more info.
2044
 
  */
2045
 
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2046
 
                                 TableIdentifier &destination_identifier,
2047
 
                                 TableIdentifier &src_table,
2048
 
                                 bool is_engine_set)
 
2524
static bool mysql_create_like_schema_frm(Session* session,
 
2525
                                         TableList* schema_table,
 
2526
                                         HA_CREATE_INFO *create_info,
 
2527
                                         drizzled::message::Table* table_proto)
2049
2528
{
2050
 
  int protoerr= EEXIST;
2051
 
  message::Table new_proto;
2052
 
  message::Table src_proto;
2053
 
 
2054
 
  protoerr= plugin::StorageEngine::getTableDefinition(session,
2055
 
                                                      src_table,
2056
 
                                                      src_proto);
2057
 
  new_proto.CopyFrom(src_proto);
2058
 
 
2059
 
  if (destination_identifier.isTmp())
2060
 
  {
2061
 
    new_proto.set_type(message::Table::TEMPORARY);
2062
 
  }
 
2529
  HA_CREATE_INFO local_create_info;
 
2530
  Alter_info alter_info;
 
2531
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
2532
  uint32_t keys= schema_table->table->s->keys;
 
2533
  uint32_t db_options= 0;
 
2534
 
 
2535
  memset(&local_create_info, 0, sizeof(local_create_info));
 
2536
  local_create_info.db_type= schema_table->table->s->db_type();
 
2537
  local_create_info.row_type= schema_table->table->s->row_type;
 
2538
  local_create_info.default_table_charset=default_charset_info;
 
2539
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
2540
  alter_info.flags.set(ALTER_RECREATE);
 
2541
  schema_table->table->use_all_columns();
 
2542
  if (mysql_prepare_alter_table(session, schema_table->table,
 
2543
                                &local_create_info, &alter_info))
 
2544
    return true;
 
2545
 
 
2546
  if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
 
2547
                                 tmp_table, &db_options,
 
2548
                                 schema_table->table->file,
 
2549
                                 &schema_table->table->s->key_info, &keys, 0))
 
2550
    return true;
 
2551
 
 
2552
  local_create_info.max_rows= 0;
 
2553
 
 
2554
  table_proto->set_name("system_stupid_i_s_fix_nonsense");
 
2555
  if(tmp_table)
 
2556
    table_proto->set_type(drizzled::message::Table::TEMPORARY);
2063
2557
  else
2064
 
  {
2065
 
    new_proto.set_type(message::Table::STANDARD);
2066
 
  }
2067
 
 
2068
 
  if (is_engine_set)
2069
 
  {
2070
 
    message::Table::StorageEngine *protoengine;
2071
 
 
2072
 
    protoengine= new_proto.mutable_engine();
2073
 
    protoengine->set_name(create_table_proto.engine().name());
2074
 
  }
2075
 
 
2076
 
  { // We now do a selective copy of elements on to the new table.
2077
 
    new_proto.set_name(create_table_proto.name());
2078
 
    new_proto.set_schema(create_table_proto.schema());
2079
 
    new_proto.set_catalog(create_table_proto.catalog());
2080
 
  }
2081
 
 
2082
 
  if (protoerr && protoerr != EEXIST)
2083
 
  {
2084
 
    if (errno == ENOENT)
2085
 
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2086
 
    else
2087
 
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2088
 
 
2089
 
    return false;
2090
 
  }
2091
 
 
2092
 
  /*
2093
 
    As mysql_truncate don't work on a new table at this stage of
2094
 
    creation, instead create the table directly (for both normal
2095
 
    and temporary tables).
2096
 
  */
2097
 
  int err= plugin::StorageEngine::createTable(session,
2098
 
                                              destination_identifier,
2099
 
                                              true, new_proto);
2100
 
 
2101
 
  return err ? false : true;
 
2558
    table_proto->set_type(drizzled::message::Table::STANDARD);
 
2559
 
 
2560
  {
 
2561
    drizzled::message::Table::StorageEngine *protoengine;
 
2562
    protoengine= table_proto->mutable_engine();
 
2563
 
 
2564
    StorageEngine *engine= local_create_info.db_type;
 
2565
 
 
2566
    protoengine->set_name(engine->getName());
 
2567
  }
 
2568
 
 
2569
  if (fill_table_proto(table_proto, "system_stupid_i_s_fix_nonsense",
 
2570
                       alter_info.create_list, &local_create_info,
 
2571
                       keys, schema_table->table->s->key_info))
 
2572
    return true;
 
2573
 
 
2574
  return false;
2102
2575
}
2103
2576
 
2104
2577
/*
2116
2589
    true  error
2117
2590
*/
2118
2591
 
2119
 
bool mysql_create_like_table(Session* session,
2120
 
                             TableIdentifier &destination_identifier,
2121
 
                             TableList* table, TableList* src_table,
2122
 
                             message::Table &create_table_proto,
2123
 
                             bool is_if_not_exists,
2124
 
                             bool is_engine_set)
 
2592
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2593
                             HA_CREATE_INFO *create_info)
2125
2594
{
2126
2595
  Table *name_lock= 0;
 
2596
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2597
  uint32_t dst_path_length;
2127
2598
  char *db= table->db;
2128
2599
  char *table_name= table->table_name;
 
2600
  int  err;
2129
2601
  bool res= true;
2130
2602
  uint32_t not_used;
2131
 
  bool was_created;
 
2603
  drizzled::message::Table src_proto;
2132
2604
 
2133
2605
  /*
2134
2606
    By opening source table we guarantee that it exists and no concurrent
2135
2607
    DDL operation will mess with it. Later we also take an exclusive
2136
 
    name-lock on target table name, which makes copying of .frm cursor,
2137
 
    call to plugin::StorageEngine::createTable() and binlogging atomic
2138
 
    against concurrent DML and DDL operations on target table.
2139
 
    Thus by holding both these "locks" we ensure that our statement is
2140
 
    properly isolated from all concurrent operations which matter.
 
2608
    name-lock on target table name, which makes copying of .frm file,
 
2609
    call to ha_create_table() and binlogging atomic against concurrent DML
 
2610
    and DDL operations on target table. Thus by holding both these "locks"
 
2611
    we ensure that our statement is properly isolated from all concurrent
 
2612
    operations which matter.
2141
2613
  */
2142
2614
  if (session->open_tables_from_list(&src_table, &not_used))
2143
2615
    return true;
2144
2616
 
2145
 
  TableIdentifier src_identifier(src_table->table->s->getSchemaName(),
2146
 
                                 src_table->table->s->table_name.str, src_table->table->s->tmp_table);
2147
 
 
2148
 
 
 
2617
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2149
2618
 
2150
2619
  /*
2151
2620
    Check that destination tables does not exist. Note that its name
2152
2621
    was already checked when it was added to the table list.
2153
2622
  */
2154
 
  bool table_exists= false;
2155
 
  if (destination_identifier.isTmp())
 
2623
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2156
2624
  {
2157
2625
    if (session->find_temporary_table(db, table_name))
2158
 
    {
2159
 
      table_exists= true;
2160
 
    }
 
2626
      goto table_exists;
 
2627
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
 
2628
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
2161
2629
  }
2162
2630
  else
2163
2631
  {
2164
2632
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2165
 
    {
2166
 
      if (name_lock)
2167
 
      {
2168
 
        pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2169
 
        session->unlink_open_table(name_lock);
2170
 
        pthread_mutex_unlock(&LOCK_open);
2171
 
      }
2172
 
 
2173
 
      return res;
2174
 
    }
2175
 
 
2176
 
    if (not name_lock)
2177
 
    {
2178
 
      table_exists= true;
2179
 
    }
2180
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2181
 
    {
2182
 
      table_exists= true;
2183
 
    }
2184
 
  }
2185
 
 
2186
 
  if (table_exists)
2187
 
  {
2188
 
    if (is_if_not_exists)
2189
 
    {
2190
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2191
 
      snprintf(warn_buff, sizeof(warn_buff),
2192
 
               ER(ER_TABLE_EXISTS_ERROR), table_name);
2193
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2194
 
                   ER_TABLE_EXISTS_ERROR,warn_buff);
2195
 
      res= false;
2196
 
    }
2197
 
    else
2198
 
    {
2199
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2200
 
    }
2201
 
  }
2202
 
  else // Otherwise we create the table
2203
 
  {
2204
 
    pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2205
 
    was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2206
 
                                      src_identifier, is_engine_set);
2207
 
    pthread_mutex_unlock(&LOCK_open);
2208
 
 
2209
 
    // So we blew the creation of the table, and we scramble to clean up
2210
 
    // anything that might have been created (read... it is a hack)
2211
 
    if (not was_created)
2212
 
    {
2213
 
      if (destination_identifier.isTmp())
2214
 
      {
2215
 
        (void) session->rm_temporary_table(destination_identifier);
2216
 
      }
2217
 
      else
2218
 
      {
2219
 
        quick_rm_table(*session, destination_identifier);
2220
 
      }
2221
 
    } 
2222
 
    else if (destination_identifier.isTmp() && not session->open_temporary_table(destination_identifier))
2223
 
    {
2224
 
      // We created, but we can't open... also, a hack.
2225
 
      (void) session->rm_temporary_table(destination_identifier);
2226
 
    }
2227
 
    else
2228
 
    {
2229
 
      if (not destination_identifier.isTmp())
2230
 
      {
2231
 
        bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
2232
 
        (void)rc;
2233
 
      }
2234
 
 
2235
 
      res= false;
2236
 
    }
2237
 
  }
2238
 
 
 
2633
      goto err;
 
2634
    if (!name_lock)
 
2635
      goto table_exists;
 
2636
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2637
                                          db, table_name, false);
 
2638
    if (StorageEngine::getTableProto(dst_path, NULL)==EEXIST)
 
2639
      goto table_exists;
 
2640
  }
 
2641
 
 
2642
  /*
 
2643
    Create a new table by copying from source table
 
2644
 
 
2645
    Altough exclusive name-lock on target table protects us from concurrent
 
2646
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2647
    to ha_create_table() in critical section protected by LOCK_open in order
 
2648
    to provide minimal atomicity against operations which disregard name-locks,
 
2649
    like I_S implementation, for example. This is a temporary and should not
 
2650
    be copied. Instead we should fix our code to always honor name-locks.
 
2651
 
 
2652
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2653
    during the call to ha_create_table(). See bug #28614 for more info.
 
2654
  */
 
2655
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2656
 
 
2657
  {
 
2658
    int protoerr= EEXIST;
 
2659
 
 
2660
    if (src_table->schema_table)
 
2661
    {
 
2662
      if (mysql_create_like_schema_frm(session, src_table, create_info,
 
2663
                                     &src_proto))
 
2664
      {
 
2665
        pthread_mutex_unlock(&LOCK_open);
 
2666
        goto err;
 
2667
      }
 
2668
    }
 
2669
    else
 
2670
    {
 
2671
      protoerr= StorageEngine::getTableProto(src_path, &src_proto);
 
2672
    }
 
2673
 
 
2674
    string dst_proto_path(dst_path);
 
2675
    string file_ext = ".dfe";
 
2676
 
 
2677
    dst_proto_path.append(file_ext);
 
2678
 
 
2679
    if (protoerr == EEXIST)
 
2680
    {
 
2681
      StorageEngine* engine= ha_resolve_by_name(session,
 
2682
                                                src_proto.engine().name());
 
2683
 
 
2684
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2685
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &src_proto);
 
2686
      else
 
2687
        protoerr= 0;
 
2688
    }
 
2689
 
 
2690
    if (protoerr)
 
2691
    {
 
2692
      if (my_errno == ENOENT)
 
2693
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2694
      else
 
2695
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2696
      pthread_mutex_unlock(&LOCK_open);
 
2697
      goto err;
 
2698
    }
 
2699
  }
 
2700
 
 
2701
  /*
 
2702
    As mysql_truncate don't work on a new table at this stage of
 
2703
    creation, instead create the table directly (for both normal
 
2704
    and temporary tables).
 
2705
  */
 
2706
 
 
2707
  err= ha_create_table(session, dst_path, db, table_name, create_info, 1,
 
2708
                       &src_proto);
 
2709
  pthread_mutex_unlock(&LOCK_open);
 
2710
 
 
2711
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2712
  {
 
2713
    if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
 
2714
    {
 
2715
      (void) session->rm_temporary_table(create_info->db_type, dst_path);
 
2716
      goto err;     /* purecov: inspected */
 
2717
    }
 
2718
  }
 
2719
  else if (err)
 
2720
  {
 
2721
    (void) quick_rm_table(create_info->db_type, db,
 
2722
                          table_name, false); /* purecov: inspected */
 
2723
    goto err;       /* purecov: inspected */
 
2724
  }
 
2725
 
 
2726
  /*
 
2727
    We have to write the query before we unlock the tables.
 
2728
  */
 
2729
  {
 
2730
    /*
 
2731
       Since temporary tables are not replicated under row-based
 
2732
       replication, CREATE TABLE ... LIKE ... needs special
 
2733
       treatement.  We have four cases to consider, according to the
 
2734
       following decision table:
 
2735
 
 
2736
           ==== ========= ========= ==============================
 
2737
           Case    Target    Source Write to binary log
 
2738
           ==== ========= ========= ==============================
 
2739
           1       normal    normal Original statement
 
2740
           2       normal temporary Generated statement
 
2741
           3    temporary    normal Nothing
 
2742
           4    temporary temporary Nothing
 
2743
           ==== ========= ========= ==============================
 
2744
    */
 
2745
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2746
    {
 
2747
      if (src_table->table->s->tmp_table)               // Case 2
 
2748
      {
 
2749
        char buf[2048];
 
2750
        String query(buf, sizeof(buf), system_charset_info);
 
2751
        query.length(0);  // Have to zero it since constructor doesn't
 
2752
 
 
2753
 
 
2754
        /*
 
2755
          Here we open the destination table, on which we already have
 
2756
          name-lock. This is needed for store_create_info() to work.
 
2757
          The table will be closed by unlink_open_table() at the end
 
2758
          of this function.
 
2759
        */
 
2760
        table->table= name_lock;
 
2761
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2762
        if (session->reopen_name_locked_table(table, false))
 
2763
        {
 
2764
          pthread_mutex_unlock(&LOCK_open);
 
2765
          goto err;
 
2766
        }
 
2767
        pthread_mutex_unlock(&LOCK_open);
 
2768
 
 
2769
        int result= store_create_info(table, &query, create_info);
 
2770
 
 
2771
        assert(result == 0); // store_create_info() always return 0
 
2772
        write_bin_log(session, true, query.ptr(), query.length());
 
2773
      }
 
2774
      else                                      // Case 1
 
2775
        write_bin_log(session, true, session->query, session->query_length);
 
2776
    }
 
2777
  }
 
2778
 
 
2779
  res= false;
 
2780
  goto err;
 
2781
 
 
2782
table_exists:
 
2783
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2784
  {
 
2785
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2786
    snprintf(warn_buff, sizeof(warn_buff),
 
2787
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2788
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2789
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2790
    res= false;
 
2791
  }
 
2792
  else
 
2793
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2794
 
 
2795
err:
2239
2796
  if (name_lock)
2240
2797
  {
2241
2798
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2242
2799
    session->unlink_open_table(name_lock);
2243
2800
    pthread_mutex_unlock(&LOCK_open);
2244
2801
  }
2245
 
 
2246
2802
  return(res);
2247
2803
}
2248
2804
 
2252
2808
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2253
2809
 
2254
2810
  return(mysql_admin_table(session, tables, check_opt,
2255
 
                                "analyze", lock_type, true,
2256
 
                                &Cursor::ha_analyze));
 
2811
                                "analyze", lock_type, 1, 0, 0, 0,
 
2812
                                &handler::ha_analyze));
2257
2813
}
2258
2814
 
2259
2815
 
2263
2819
 
2264
2820
  return(mysql_admin_table(session, tables, check_opt,
2265
2821
                                "check", lock_type,
2266
 
                                false,
2267
 
                                &Cursor::ha_check));
 
2822
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
2823
                                &handler::ha_check));
 
2824
}
 
2825
 
 
2826
 
 
2827
/* table_list should contain just one table */
 
2828
static int
 
2829
mysql_discard_or_import_tablespace(Session *session,
 
2830
                                   TableList *table_list,
 
2831
                                   enum tablespace_op_type tablespace_op)
 
2832
{
 
2833
  Table *table;
 
2834
  bool discard;
 
2835
  int error;
 
2836
 
 
2837
  /*
 
2838
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
 
2839
    ALTER Table
 
2840
  */
 
2841
 
 
2842
  session->set_proc_info("discard_or_import_tablespace");
 
2843
 
 
2844
  discard= test(tablespace_op == DISCARD_TABLESPACE);
 
2845
 
 
2846
 /*
 
2847
   We set this flag so that ha_innobase::open and ::external_lock() do
 
2848
   not complain when we lock the table
 
2849
 */
 
2850
  session->tablespace_op= true;
 
2851
  if (!(table= session->openTableLock(table_list, TL_WRITE)))
 
2852
  {
 
2853
    session->tablespace_op= false;
 
2854
    return -1;
 
2855
  }
 
2856
 
 
2857
  error= table->file->ha_discard_or_import_tablespace(discard);
 
2858
 
 
2859
  session->set_proc_info("end");
 
2860
 
 
2861
  if (error)
 
2862
    goto err;
 
2863
 
 
2864
  /* The ALTER Table is always in its own transaction */
 
2865
  error = ha_autocommit_or_rollback(session, 0);
 
2866
  if (! session->endActiveTransaction())
 
2867
    error=1;
 
2868
  if (error)
 
2869
    goto err;
 
2870
  write_bin_log(session, false, session->query, session->query_length);
 
2871
 
 
2872
err:
 
2873
  ha_autocommit_or_rollback(session, error);
 
2874
  session->tablespace_op=false;
 
2875
 
 
2876
  if (error == 0)
 
2877
  {
 
2878
    session->my_ok();
 
2879
    return 0;
 
2880
  }
 
2881
 
 
2882
  table->file->print_error(error, MYF(0));
 
2883
 
 
2884
  return -1;
 
2885
}
 
2886
 
 
2887
 
 
2888
/*
 
2889
  Manages enabling/disabling of indexes for ALTER Table
 
2890
 
 
2891
  SYNOPSIS
 
2892
    alter_table_manage_keys()
 
2893
      table                  Target table
 
2894
      indexes_were_disabled  Whether the indexes of the from table
 
2895
                             were disabled
 
2896
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
 
2897
 
 
2898
  RETURN VALUES
 
2899
    false  OK
 
2900
    true   Error
 
2901
*/
 
2902
 
 
2903
static
 
2904
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
 
2905
                             enum enum_enable_or_disable keys_onoff)
 
2906
{
 
2907
  int error= 0;
 
2908
  switch (keys_onoff) {
 
2909
  case ENABLE:
 
2910
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
2911
    break;
 
2912
  case LEAVE_AS_IS:
 
2913
    if (!indexes_were_disabled)
 
2914
      break;
 
2915
    /* fall-through: disabled indexes */
 
2916
  case DISABLE:
 
2917
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
2918
  }
 
2919
 
 
2920
  if (error == HA_ERR_WRONG_COMMAND)
 
2921
  {
 
2922
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2923
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
2924
                        table->s->table_name.str);
 
2925
    error= 0;
 
2926
  } else if (error)
 
2927
    table->file->print_error(error, MYF(0));
 
2928
 
 
2929
  return(error);
 
2930
}
 
2931
 
 
2932
static int 
 
2933
create_temporary_table(Session *session,
 
2934
                       Table *table,
 
2935
                       char *new_db,
 
2936
                       char *tmp_name,
 
2937
                       HA_CREATE_INFO *create_info,
 
2938
                       Alter_info *alter_info,
 
2939
                       bool db_changed)
 
2940
{
 
2941
  int error;
 
2942
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
 
2943
  StorageEngine *old_db_type, *new_db_type;
 
2944
  old_db_type= table->s->db_type();
 
2945
  new_db_type= create_info->db_type;
 
2946
  /*
 
2947
    Handling of symlinked tables:
 
2948
    If no rename:
 
2949
      Create new data file and index file on the same disk as the
 
2950
      old data and index files.
 
2951
      Copy data.
 
2952
      Rename new data file over old data file and new index file over
 
2953
      old index file.
 
2954
      Symlinks are not changed.
 
2955
 
 
2956
   If rename:
 
2957
      Create new data file and index file on the same disk as the
 
2958
      old data and index files.  Create also symlinks to point at
 
2959
      the new tables.
 
2960
      Copy data.
 
2961
      At end, rename intermediate tables, and symlinks to intermediate
 
2962
      table, to final table name.
 
2963
      Remove old table and old symlinks
 
2964
 
 
2965
    If rename is made to another database:
 
2966
      Create new tables in new database.
 
2967
      Copy data.
 
2968
      Remove old table and symlinks.
 
2969
  */
 
2970
  if (db_changed)               // Ignore symlink if db changed
 
2971
  {
 
2972
    if (create_info->index_file_name)
 
2973
    {
 
2974
      /* Fix index_file_name to have 'tmp_name' as basename */
 
2975
      strcpy(index_file, tmp_name);
 
2976
      create_info->index_file_name=fn_same(index_file,
 
2977
                                           create_info->index_file_name,
 
2978
                                           1);
 
2979
    }
 
2980
    if (create_info->data_file_name)
 
2981
    {
 
2982
      /* Fix data_file_name to have 'tmp_name' as basename */
 
2983
      strcpy(data_file, tmp_name);
 
2984
      create_info->data_file_name=fn_same(data_file,
 
2985
                                          create_info->data_file_name,
 
2986
                                          1);
 
2987
    }
 
2988
  }
 
2989
  else
 
2990
    create_info->data_file_name=create_info->index_file_name=0;
 
2991
 
 
2992
  /*
 
2993
    Create a table with a temporary name.
 
2994
    We don't log the statement, it will be logged later.
 
2995
  */
 
2996
  drizzled::message::Table table_proto;
 
2997
  table_proto.set_name(tmp_name);
 
2998
  table_proto.set_type(drizzled::message::Table::TEMPORARY);
 
2999
 
 
3000
  drizzled::message::Table::StorageEngine *protoengine;
 
3001
  protoengine= table_proto.mutable_engine();
 
3002
  protoengine->set_name(new_db_type->getName());
 
3003
 
 
3004
  error= mysql_create_table(session, new_db, tmp_name,
 
3005
                            create_info, &table_proto, alter_info, 1, 0);
 
3006
 
 
3007
  return(error);
 
3008
}
 
3009
 
 
3010
 
 
3011
/**
 
3012
  Prepare column and key definitions for CREATE TABLE in ALTER Table.
 
3013
 
 
3014
  This function transforms parse output of ALTER Table - lists of
 
3015
  columns and keys to add, drop or modify into, essentially,
 
3016
  CREATE TABLE definition - a list of columns and keys of the new
 
3017
  table. While doing so, it also performs some (bug not all)
 
3018
  semantic checks.
 
3019
 
 
3020
  This function is invoked when we know that we're going to
 
3021
  perform ALTER Table via a temporary table -- i.e. fast ALTER Table
 
3022
  is not possible, perhaps because the ALTER statement contains
 
3023
  instructions that require change in table data, not only in
 
3024
  table definition or indexes.
 
3025
 
 
3026
  @param[in,out]  session         thread handle. Used as a memory pool
 
3027
                              and source of environment information.
 
3028
  @param[in]      table       the source table, open and locked
 
3029
                              Used as an interface to the storage engine
 
3030
                              to acquire additional information about
 
3031
                              the original table.
 
3032
  @param[in,out]  create_info A blob with CREATE/ALTER Table
 
3033
                              parameters
 
3034
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
 
3035
                              Originally create_info was used only in
 
3036
                              CREATE TABLE and alter_info only in ALTER Table.
 
3037
                              But since ALTER might end-up doing CREATE,
 
3038
                              this distinction is gone and we just carry
 
3039
                              around two structures.
 
3040
 
 
3041
  @return
 
3042
    Fills various create_info members based on information retrieved
 
3043
    from the storage engine.
 
3044
    Sets create_info->varchar if the table has a VARCHAR column.
 
3045
    Prepares alter_info->create_list and alter_info->key_list with
 
3046
    columns and keys of the new table.
 
3047
  @retval true   error, out of memory or a semantical error in ALTER
 
3048
                 Table instructions
 
3049
  @retval false  success
 
3050
*/
 
3051
 
 
3052
static bool
 
3053
mysql_prepare_alter_table(Session *session, Table *table,
 
3054
                          HA_CREATE_INFO *create_info,
 
3055
                          Alter_info *alter_info)
 
3056
{
 
3057
  /* New column definitions are added here */
 
3058
  List<CreateField> new_create_list;
 
3059
  /* New key definitions are added here */
 
3060
  List<Key> new_key_list;
 
3061
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
 
3062
  List_iterator<CreateField> def_it(alter_info->create_list);
 
3063
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
 
3064
  List_iterator<Key> key_it(alter_info->key_list);
 
3065
  List_iterator<CreateField> find_it(new_create_list);
 
3066
  List_iterator<CreateField> field_it(new_create_list);
 
3067
  List<Key_part_spec> key_parts;
 
3068
  uint32_t db_create_options= (table->s->db_create_options
 
3069
                           & ~(HA_OPTION_PACK_RECORD));
 
3070
  uint32_t used_fields= create_info->used_fields;
 
3071
  KEY *key_info=table->key_info;
 
3072
  bool rc= true;
 
3073
 
 
3074
 
 
3075
  create_info->varchar= false;
 
3076
  /* Let new create options override the old ones */
 
3077
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
 
3078
    create_info->min_rows= table->s->min_rows;
 
3079
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
 
3080
    create_info->max_rows= table->s->max_rows;
 
3081
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
 
3082
    create_info->avg_row_length= table->s->avg_row_length;
 
3083
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
3084
    create_info->block_size= table->s->block_size;
 
3085
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
3086
    create_info->default_table_charset= table->s->table_charset;
 
3087
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
3088
    {
 
3089
    /* Table has an autoincrement, copy value to new table */
 
3090
    table->file->info(HA_STATUS_AUTO);
 
3091
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
 
3092
  }
 
3093
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
3094
    create_info->key_block_size= table->s->key_block_size;
 
3095
 
 
3096
  table->restoreRecordAsDefault();     // Empty record for DEFAULT
 
3097
  CreateField *def;
 
3098
 
 
3099
    /*
 
3100
    First collect all fields from table which isn't in drop_list
 
3101
    */
 
3102
  Field **f_ptr,*field;
 
3103
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
 
3104
  {
 
3105
    /* Check if field should be dropped */
 
3106
    Alter_drop *drop;
 
3107
    drop_it.rewind();
 
3108
    while ((drop=drop_it++))
 
3109
    {
 
3110
      if (drop->type == Alter_drop::COLUMN &&
 
3111
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
 
3112
      {
 
3113
        /* Reset auto_increment value if it was dropped */
 
3114
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
3115
            !(used_fields & HA_CREATE_USED_AUTO))
 
3116
        {
 
3117
          create_info->auto_increment_value=0;
 
3118
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
3119
        }
 
3120
        break;
 
3121
      }
 
3122
    }
 
3123
    if (drop)
 
3124
    {
 
3125
      drop_it.remove();
 
3126
      continue;
 
3127
    }
 
3128
    
 
3129
    /* Mark that we will read the field */
 
3130
    field->setReadSet();
 
3131
 
 
3132
    /* Check if field is changed */
 
3133
    def_it.rewind();
 
3134
    while ((def=def_it++))
 
3135
    {
 
3136
      if (def->change &&
 
3137
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
3138
        break;
 
3139
    }
 
3140
    if (def)
 
3141
    {                                           // Field is changed
 
3142
      def->field=field;
 
3143
      if (!def->after)
 
3144
      {
 
3145
        new_create_list.push_back(def);
 
3146
        def_it.remove();
 
3147
      }
 
3148
    }
 
3149
    else
 
3150
    {
 
3151
      /*
 
3152
        This field was not dropped and not changed, add it to the list
 
3153
        for the new table.
 
3154
      */
 
3155
      def= new CreateField(field, field);
 
3156
      new_create_list.push_back(def);
 
3157
      alter_it.rewind();                        // Change default if ALTER
 
3158
      Alter_column *alter;
 
3159
      while ((alter=alter_it++))
 
3160
      {
 
3161
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
3162
          break;
 
3163
      }
 
3164
      if (alter)
 
3165
      {
 
3166
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
 
3167
        {
 
3168
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
3169
          goto err;
 
3170
        }
 
3171
        if ((def->def=alter->def))              // Use new default
 
3172
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
 
3173
        else
 
3174
          def->flags|= NO_DEFAULT_VALUE_FLAG;
 
3175
        alter_it.remove();
 
3176
      }
 
3177
    }
 
3178
  }
 
3179
  def_it.rewind();
 
3180
  while ((def=def_it++))                        // Add new columns
 
3181
  {
 
3182
    if (def->change && ! def->field)
 
3183
    {
 
3184
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
3185
      goto err;
 
3186
    }
 
3187
    /*
 
3188
      Check that the DATE/DATETIME not null field we are going to add is
 
3189
      either has a default value or the '0000-00-00' is allowed by the
 
3190
      set sql mode.
 
3191
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
3192
      flag to allow ALTER Table only if the table to be altered is empty.
 
3193
    */
 
3194
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
3195
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
3196
        !alter_info->datetime_field &&
 
3197
        !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
3198
        session->variables.sql_mode & MODE_NO_ZERO_DATE)
 
3199
    {
 
3200
      alter_info->datetime_field= def;
 
3201
      alter_info->error_if_not_empty= true;
 
3202
    }
 
3203
    if (!def->after)
 
3204
      new_create_list.push_back(def);
 
3205
    else if (def->after == first_keyword)
 
3206
      new_create_list.push_front(def);
 
3207
    else
 
3208
    {
 
3209
      CreateField *find;
 
3210
      find_it.rewind();
 
3211
      while ((find=find_it++))                  // Add new columns
 
3212
      {
 
3213
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
3214
          break;
 
3215
      }
 
3216
      if (!find)
 
3217
      {
 
3218
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
3219
        goto err;
 
3220
      }
 
3221
      find_it.after(def);                       // Put element after this
 
3222
      /*
 
3223
        XXX: hack for Bug#28427.
 
3224
        If column order has changed, force OFFLINE ALTER Table
 
3225
        without querying engine capabilities.  If we ever have an
 
3226
        engine that supports online ALTER Table CHANGE COLUMN
 
3227
        <name> AFTER <name1> (Falcon?), this fix will effectively
 
3228
        disable the capability.
 
3229
        TODO: detect the situation in compare_tables, behave based
 
3230
        on engine capabilities.
 
3231
      */
 
3232
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
3233
      {
 
3234
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
3235
        goto err;
 
3236
      }
 
3237
      alter_info->build_method= HA_BUILD_OFFLINE;
 
3238
    }
 
3239
  }
 
3240
  if (alter_info->alter_list.elements)
 
3241
  {
 
3242
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
3243
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
3244
    goto err;
 
3245
  }
 
3246
  if (!new_create_list.elements)
 
3247
  {
 
3248
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
 
3249
               MYF(0));
 
3250
    goto err;
 
3251
  }
 
3252
 
 
3253
  /*
 
3254
    Collect all keys which isn't in drop list. Add only those
 
3255
    for which some fields exists.
 
3256
  */
 
3257
 
 
3258
  for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
 
3259
  {
 
3260
    char *key_name= key_info->name;
 
3261
    Alter_drop *drop;
 
3262
    drop_it.rewind();
 
3263
    while ((drop=drop_it++))
 
3264
    {
 
3265
      if (drop->type == Alter_drop::KEY &&
 
3266
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
3267
        break;
 
3268
    }
 
3269
    if (drop)
 
3270
    {
 
3271
      drop_it.remove();
 
3272
      continue;
 
3273
    }
 
3274
 
 
3275
    KEY_PART_INFO *key_part= key_info->key_part;
 
3276
    key_parts.empty();
 
3277
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
3278
    {
 
3279
      if (!key_part->field)
 
3280
        continue;                               // Wrong field (from UNIREG)
 
3281
      const char *key_part_name=key_part->field->field_name;
 
3282
      CreateField *cfield;
 
3283
      field_it.rewind();
 
3284
      while ((cfield=field_it++))
 
3285
      {
 
3286
        if (cfield->change)
 
3287
        {
 
3288
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
3289
                             cfield->change))
 
3290
            break;
 
3291
        }
 
3292
        else if (!my_strcasecmp(system_charset_info,
 
3293
                                key_part_name, cfield->field_name))
 
3294
          break;
 
3295
      }
 
3296
      if (!cfield)
 
3297
        continue;                               // Field is removed
 
3298
      uint32_t key_part_length=key_part->length;
 
3299
      if (cfield->field)                        // Not new field
 
3300
      {
 
3301
        /*
 
3302
          If the field can't have only a part used in a key according to its
 
3303
          new type, or should not be used partially according to its
 
3304
          previous type, or the field length is less than the key part
 
3305
          length, unset the key part length.
 
3306
 
 
3307
          We also unset the key part length if it is the same as the
 
3308
          old field's length, so the whole new field will be used.
 
3309
 
 
3310
          BLOBs may have cfield->length == 0, which is why we test it before
 
3311
          checking whether cfield->length < key_part_length (in chars).
 
3312
         */
 
3313
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
3314
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
3315
            (cfield->field->field_length == key_part_length &&
 
3316
             !f_is_blob(key_part->key_type)) ||
 
3317
            (cfield->length && (cfield->length < key_part_length /
 
3318
                                key_part->field->charset()->mbmaxlen)))
 
3319
          key_part_length= 0;                   // Use whole field
 
3320
      }
 
3321
      key_part_length /= key_part->field->charset()->mbmaxlen;
 
3322
      key_parts.push_back(new Key_part_spec(cfield->field_name,
 
3323
                                            strlen(cfield->field_name),
 
3324
                                            key_part_length));
 
3325
    }
 
3326
    if (key_parts.elements)
 
3327
    {
 
3328
      KEY_CREATE_INFO key_create_info;
 
3329
      Key *key;
 
3330
      enum Key::Keytype key_type;
 
3331
      memset(&key_create_info, 0, sizeof(key_create_info));
 
3332
 
 
3333
      key_create_info.algorithm= key_info->algorithm;
 
3334
      if (key_info->flags & HA_USES_BLOCK_SIZE)
 
3335
        key_create_info.block_size= key_info->block_size;
 
3336
      if (key_info->flags & HA_USES_COMMENT)
 
3337
        key_create_info.comment= key_info->comment;
 
3338
 
 
3339
      if (key_info->flags & HA_NOSAME)
 
3340
      {
 
3341
        if (is_primary_key_name(key_name))
 
3342
          key_type= Key::PRIMARY;
 
3343
        else
 
3344
          key_type= Key::UNIQUE;
 
3345
      }
 
3346
      else
 
3347
        key_type= Key::MULTIPLE;
 
3348
 
 
3349
      key= new Key(key_type, key_name, strlen(key_name),
 
3350
                   &key_create_info,
 
3351
                   test(key_info->flags & HA_GENERATED_KEY),
 
3352
                   key_parts);
 
3353
      new_key_list.push_back(key);
 
3354
    }
 
3355
  }
 
3356
  {
 
3357
    Key *key;
 
3358
    while ((key=key_it++))                      // Add new keys
 
3359
    {
 
3360
      if (key->type == Key::FOREIGN_KEY &&
 
3361
          ((Foreign_key *)key)->validate(new_create_list))
 
3362
        goto err;
 
3363
      if (key->type != Key::FOREIGN_KEY)
 
3364
        new_key_list.push_back(key);
 
3365
      if (key->name.str && is_primary_key_name(key->name.str))
 
3366
      {
 
3367
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
3368
        goto err;
 
3369
      }
 
3370
    }
 
3371
  }
 
3372
 
 
3373
  if (alter_info->drop_list.elements)
 
3374
  {
 
3375
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
3376
             alter_info->drop_list.head()->name);
 
3377
    goto err;
 
3378
  }
 
3379
  if (alter_info->alter_list.elements)
 
3380
  {
 
3381
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
3382
             alter_info->alter_list.head()->name);
 
3383
    goto err;
 
3384
  }
 
3385
 
 
3386
  if (!create_info->comment.str)
 
3387
  {
 
3388
    create_info->comment.str= table->s->comment.str;
 
3389
    create_info->comment.length= table->s->comment.length;
 
3390
  }
 
3391
 
 
3392
  table->file->update_create_info(create_info);
 
3393
  if ((create_info->table_options &
 
3394
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
 
3395
      (used_fields & HA_CREATE_USED_PACK_KEYS))
 
3396
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
 
3397
  if (create_info->table_options &
 
3398
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
 
3399
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
 
3400
  if (create_info->table_options &
 
3401
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
 
3402
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
 
3403
                          HA_OPTION_NO_DELAY_KEY_WRITE);
 
3404
  create_info->table_options|= db_create_options;
 
3405
 
 
3406
  if (table->s->tmp_table)
 
3407
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
3408
 
 
3409
  rc= false;
 
3410
  alter_info->create_list.swap(new_create_list);
 
3411
  alter_info->key_list.swap(new_key_list);
 
3412
err:
 
3413
  return(rc);
 
3414
}
 
3415
 
 
3416
 
 
3417
/*
 
3418
  Alter table
 
3419
 
 
3420
  SYNOPSIS
 
3421
    mysql_alter_table()
 
3422
      session              Thread handle
 
3423
      new_db           If there is a RENAME clause
 
3424
      new_name         If there is a RENAME clause
 
3425
      create_info      Information from the parsing phase about new
 
3426
                       table properties.
 
3427
      table_list       The table to change.
 
3428
      alter_info       Lists of fields, keys to be changed, added
 
3429
                       or dropped.
 
3430
      order_num        How many order_st BY fields has been specified.
 
3431
      order            List of fields to order_st BY.
 
3432
      ignore           Whether we have ALTER IGNORE Table
 
3433
 
 
3434
  DESCRIPTION
 
3435
    This is a veery long function and is everything but the kitchen sink :)
 
3436
    It is used to alter a table and not only by ALTER Table but also
 
3437
    CREATE|DROP INDEX are mapped on this function.
 
3438
 
 
3439
    When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
 
3440
    or both, then this function short cuts its operation by renaming
 
3441
    the table and/or enabling/disabling the keys. In this case, the FRM is
 
3442
    not changed, directly by mysql_alter_table. However, if there is a
 
3443
    RENAME + change of a field, or an index, the short cut is not used.
 
3444
    See how `create_list` is used to generate the new FRM regarding the
 
3445
    structure of the fields. The same is done for the indices of the table.
 
3446
 
 
3447
    Important is the fact, that this function tries to do as little work as
 
3448
    possible, by finding out whether a intermediate table is needed to copy
 
3449
    data into and when finishing the altering to use it as the original table.
 
3450
    For this reason the function compare_tables() is called, which decides
 
3451
    based on all kind of data how similar are the new and the original
 
3452
    tables.
 
3453
 
 
3454
  RETURN VALUES
 
3455
    false  OK
 
3456
    true   Error
 
3457
*/
 
3458
 
 
3459
bool mysql_alter_table(Session *session, 
 
3460
                       char *new_db, 
 
3461
                       char *new_name,
 
3462
                       HA_CREATE_INFO *create_info,
 
3463
                       TableList *table_list,
 
3464
                       Alter_info *alter_info,
 
3465
                       uint32_t order_num, 
 
3466
                       order_st *order, 
 
3467
                       bool ignore)
 
3468
{
 
3469
  Table *table;
 
3470
  Table *new_table= NULL;
 
3471
  Table *name_lock= NULL;
 
3472
  string new_name_str;
 
3473
  int error= 0;
 
3474
  char tmp_name[80];
 
3475
  char old_name[32];
 
3476
  char new_name_buff[FN_REFLEN];
 
3477
  char new_alias_buff[FN_REFLEN];
 
3478
  char *table_name;
 
3479
  char *db;
 
3480
  const char *new_alias;
 
3481
  char path[FN_REFLEN];
 
3482
  ha_rows copied= 0;
 
3483
  ha_rows deleted= 0;
 
3484
  StorageEngine *old_db_type;
 
3485
  StorageEngine *new_db_type;
 
3486
  StorageEngine *save_old_db_type;
 
3487
  bitset<32> tmp;
 
3488
 
 
3489
  new_name_buff[0]= '\0';
 
3490
 
 
3491
  if (table_list && table_list->schema_table)
 
3492
  {
 
3493
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
3494
    return true;
 
3495
  }
 
3496
 
 
3497
  session->set_proc_info("init");
 
3498
 
 
3499
  /*
 
3500
    Assign variables table_name, new_name, db, new_db, path
 
3501
    to simplify further comparisons: we want to see if it's a RENAME
 
3502
    later just by comparing the pointers, avoiding the need for strcmp.
 
3503
  */
 
3504
  table_name= table_list->table_name;
 
3505
  db= table_list->db;
 
3506
  if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
 
3507
    new_db= db;
 
3508
 
 
3509
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
3510
  {
 
3511
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
3512
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
 
3513
  }
 
3514
 
 
3515
  build_table_filename(path, sizeof(path), db, table_name, false);
 
3516
 
 
3517
  ostringstream oss;
 
3518
  oss << drizzle_data_home << "/" << db << "/" << table_name;
 
3519
 
 
3520
  (void) unpack_filename(new_name_buff, oss.str().c_str());
 
3521
 
 
3522
  /*
 
3523
    If this is just a rename of a view, short cut to the
 
3524
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
3525
    2) unlock LOCK_open.
 
3526
    This is a copy-paste added to make sure
 
3527
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
 
3528
    as an independent branch in mysql_execute_command. The need
 
3529
    for a copy-paste arose because the main code flow of ALTER Table
 
3530
    ... RENAME tries to use openTableLock, which does not work for views
 
3531
    (openTableLock was never modified to merge table lists of child tables
 
3532
    into the main table list, like open_tables does).
 
3533
    This code is wrong and will be removed, please do not copy.
 
3534
  */
 
3535
 
 
3536
  if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
 
3537
    return true;
 
3538
  
 
3539
  table->use_all_columns();
 
3540
 
 
3541
  /* Check that we are not trying to rename to an existing table */
 
3542
  if (new_name)
 
3543
  {
 
3544
    strcpy(new_name_buff, new_name);
 
3545
    strcpy(new_alias_buff, new_name);
 
3546
    new_alias= new_alias_buff;
 
3547
 
 
3548
    my_casedn_str(files_charset_info, new_name_buff);
 
3549
    new_alias= new_name; // Create lower case table name
 
3550
    my_casedn_str(files_charset_info, new_name);
 
3551
 
 
3552
    if (new_db == db &&
 
3553
        ! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
3554
    {
 
3555
      /*
 
3556
        Source and destination table names are equal: make later check
 
3557
        easier.
 
3558
      */
 
3559
      new_alias= new_name= table_name;
 
3560
    }
 
3561
    else
 
3562
    {
 
3563
      if (table->s->tmp_table != NO_TMP_TABLE)
 
3564
      {
 
3565
        if (session->find_temporary_table(new_db, new_name_buff))
 
3566
        {
 
3567
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
3568
          return true;
 
3569
        }
 
3570
      }
 
3571
      else
 
3572
      {
 
3573
        if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
 
3574
          return true;
 
3575
 
 
3576
        if (! name_lock)
 
3577
        {
 
3578
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
3579
          return true;
 
3580
        }
 
3581
 
 
3582
        build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
 
3583
 
 
3584
        if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
 
3585
        {
 
3586
          /* Table will be closed by Session::executeCommand() */
 
3587
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
3588
          goto err;
 
3589
        }
 
3590
      }
 
3591
    }
 
3592
  }
 
3593
  else
 
3594
  {
 
3595
    new_alias= table_name;
 
3596
    new_name= table_name;
 
3597
  }
 
3598
 
 
3599
  old_db_type= table->s->db_type();
 
3600
  if (! create_info->db_type)
 
3601
  {
 
3602
    create_info->db_type= old_db_type;
 
3603
  }
 
3604
 
 
3605
  if (table->s->tmp_table != NO_TMP_TABLE)
 
3606
    create_info->options|= HA_LEX_CREATE_TMP_TABLE;
 
3607
 
 
3608
  if (check_engine(session, new_name, create_info))
 
3609
    goto err;
 
3610
 
 
3611
  new_db_type= create_info->db_type;
 
3612
 
 
3613
  if (new_db_type != old_db_type &&
 
3614
      !table->file->can_switch_engines())
 
3615
  {
 
3616
    assert(0);
 
3617
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
 
3618
    goto err;
 
3619
  }
 
3620
 
 
3621
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
3622
    create_info->row_type= table->s->row_type;
 
3623
 
 
3624
  if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
 
3625
      new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
 
3626
  {
 
3627
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
3628
    goto err;
 
3629
  }
 
3630
 
 
3631
  session->set_proc_info("setup");
 
3632
  
 
3633
  /*
 
3634
   * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
 
3635
   */
 
3636
  tmp.set();
 
3637
  tmp.reset(ALTER_RENAME);
 
3638
  tmp.reset(ALTER_KEYS_ONOFF);
 
3639
  tmp&= alter_info->flags;
 
3640
  if (! (tmp.any()) &&
 
3641
      ! table->s->tmp_table) // no need to touch frm
 
3642
  {
 
3643
    switch (alter_info->keys_onoff)
 
3644
    {
 
3645
    case LEAVE_AS_IS:
 
3646
      break;
 
3647
    case ENABLE:
 
3648
      /*
 
3649
        wait_while_table_is_used() ensures that table being altered is
 
3650
        opened only by this thread and that Table::TableShare::version
 
3651
        of Table object corresponding to this table is 0.
 
3652
        The latter guarantees that no DML statement will open this table
 
3653
        until ALTER Table finishes (i.e. until close_thread_tables())
 
3654
        while the fact that the table is still open gives us protection
 
3655
        from concurrent DDL statements.
 
3656
      */
 
3657
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
3658
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
3659
      pthread_mutex_unlock(&LOCK_open);
 
3660
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3661
      /* COND_refresh will be signaled in close_thread_tables() */
 
3662
      break;
 
3663
    case DISABLE:
 
3664
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
3665
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
3666
      pthread_mutex_unlock(&LOCK_open);
 
3667
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3668
      /* COND_refresh will be signaled in close_thread_tables() */
 
3669
      break;
 
3670
    default:
 
3671
      assert(false);
 
3672
      error= 0;
 
3673
      break;
 
3674
    }
 
3675
 
 
3676
    if (error == HA_ERR_WRONG_COMMAND)
 
3677
    {
 
3678
      error= 0;
 
3679
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3680
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3681
                          table->alias);
 
3682
    }
 
3683
 
 
3684
    pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
 
3685
    /*
 
3686
      Unlike to the above case close_cached_table() below will remove ALL
 
3687
      instances of Table from table cache (it will also remove table lock
 
3688
      held by this thread). So to make actual table renaming and writing
 
3689
      to binlog atomic we have to put them into the same critical section
 
3690
      protected by LOCK_open mutex. This also removes gap for races between
 
3691
      access() and mysql_rename_table() calls.
 
3692
    */
 
3693
 
 
3694
    if (error == 0 && 
 
3695
        (new_name != table_name || new_db != db))
 
3696
    {
 
3697
      session->set_proc_info("rename");
 
3698
      /*
 
3699
        Then do a 'simple' rename of the table. First we need to close all
 
3700
        instances of 'source' table.
 
3701
      */
 
3702
      session->close_cached_table(table);
 
3703
      /*
 
3704
        Then, we want check once again that target table does not exist.
 
3705
        Actually the order of these two steps does not matter since
 
3706
        earlier we took name-lock on the target table, so we do them
 
3707
        in this particular order only to be consistent with 5.0, in which
 
3708
        we don't take this name-lock and where this order really matters.
 
3709
        TODO: Investigate if we need this access() check at all.
 
3710
      */
 
3711
      if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
 
3712
      {
 
3713
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
3714
        error= -1;
 
3715
      }
 
3716
      else
 
3717
      {
 
3718
        *fn_ext(new_name)= 0;
 
3719
        if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
 
3720
          error= -1;
 
3721
      }
 
3722
    }
 
3723
 
 
3724
    if (error == HA_ERR_WRONG_COMMAND)
 
3725
    {
 
3726
      error= 0;
 
3727
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3728
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3729
                          table->alias);
 
3730
    }
 
3731
 
 
3732
    if (error == 0)
 
3733
    {
 
3734
      write_bin_log(session, true, session->query, session->query_length);
 
3735
      session->my_ok();
 
3736
    }
 
3737
    else if (error > 0)
 
3738
    {
 
3739
      table->file->print_error(error, MYF(0));
 
3740
      error= -1;
 
3741
    }
 
3742
 
 
3743
    if (name_lock)
 
3744
      session->unlink_open_table(name_lock);
 
3745
 
 
3746
    pthread_mutex_unlock(&LOCK_open);
 
3747
    table_list->table= NULL;
 
3748
    return error;
 
3749
  }
 
3750
 
 
3751
  /* We have to do full alter table. */
 
3752
 
 
3753
  /*
 
3754
    If the old table had partitions and we are doing ALTER Table ...
 
3755
    engine= <new_engine>, the new table must preserve the original
 
3756
    partitioning. That means that the new engine is still the
 
3757
    partitioning engine, not the engine specified in the parser.
 
3758
    This is discovered  in prep_alter_part_table, which in such case
 
3759
    updates create_info->db_type.
 
3760
    Now we need to update the stack copy of create_info->db_type,
 
3761
    as otherwise we won't be able to correctly move the files of the
 
3762
    temporary table to the result table files.
 
3763
  */
 
3764
  new_db_type= create_info->db_type;
 
3765
 
 
3766
  if (mysql_prepare_alter_table(session, table, create_info, alter_info))
 
3767
    goto err;
 
3768
 
 
3769
  set_table_default_charset(create_info, db);
 
3770
 
 
3771
  alter_info->build_method= HA_BUILD_OFFLINE;
 
3772
 
 
3773
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
3774
  
 
3775
  /* Safety fix for innodb */
 
3776
  my_casedn_str(files_charset_info, tmp_name);
 
3777
 
 
3778
  /* Create a temporary table with the new format */
 
3779
  error= create_temporary_table(session, table, new_db, tmp_name, create_info, alter_info, ! strcmp(db, new_db));
 
3780
 
 
3781
  if (error != 0)
 
3782
    goto err;
 
3783
 
 
3784
  /* Open the table so we need to copy the data to it. */
 
3785
  if (table->s->tmp_table)
 
3786
  {
 
3787
    TableList tbl;
 
3788
    tbl.db= new_db;
 
3789
    tbl.alias= tmp_name;
 
3790
    tbl.table_name= tmp_name;
 
3791
 
 
3792
    /* Table is in session->temporary_tables */
 
3793
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
 
3794
  }
 
3795
  else
 
3796
  {
 
3797
    char tmp_path[FN_REFLEN];
 
3798
    /* table is a normal table: Create temporary table in same directory */
 
3799
    build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
 
3800
    /* Open our intermediate table */
 
3801
    new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
 
3802
  }
 
3803
 
 
3804
  if (new_table == NULL)
 
3805
    goto err1;
 
3806
 
 
3807
  /* Copy the data if necessary. */
 
3808
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
 
3809
  session->cuted_fields= 0L;
 
3810
  session->set_proc_info("copy to tmp table");
 
3811
  copied= deleted= 0;
 
3812
 
 
3813
  assert(new_table);
 
3814
 
 
3815
  /* We don't want update TIMESTAMP fields during ALTER Table. */
 
3816
  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
3817
  new_table->next_number_field= new_table->found_next_number_field;
 
3818
  error= copy_data_between_tables(table, 
 
3819
                                  new_table,
 
3820
                                  alter_info->create_list, 
 
3821
                                  ignore,
 
3822
                                  order_num, 
 
3823
                                  order, 
 
3824
                                  &copied, 
 
3825
                                  &deleted,
 
3826
                                  alter_info->keys_onoff,
 
3827
                                  alter_info->error_if_not_empty);
 
3828
 
 
3829
  /* We must not ignore bad input! */
 
3830
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
3831
 
 
3832
  if (table->s->tmp_table != NO_TMP_TABLE)
 
3833
  {
 
3834
    /* We changed a temporary table */
 
3835
    if (error)
 
3836
      goto err1;
 
3837
 
 
3838
    /* Close lock if this is a transactional table */
 
3839
    if (session->lock)
 
3840
    {
 
3841
      mysql_unlock_tables(session, session->lock);
 
3842
      session->lock= 0;
 
3843
    }
 
3844
 
 
3845
    /* Remove link to old table and rename the new one */
 
3846
    session->close_temporary_table(table, true, true);
 
3847
 
 
3848
    /* Should pass the 'new_name' as we store table name in the cache */
 
3849
    if (new_table->rename_temporary_table(new_db, new_name))
 
3850
      goto err1;
 
3851
    
 
3852
    goto end_temporary;
 
3853
  }
 
3854
 
 
3855
  if (new_table)
 
3856
  {
 
3857
    /*
 
3858
      Close the intermediate table that will be the new table.
 
3859
      Note that MERGE tables do not have their children attached here.
 
3860
    */
 
3861
    new_table->intern_close_table();
 
3862
    free(new_table);
 
3863
  }
 
3864
 
 
3865
  pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
 
3866
  
 
3867
  if (error)
 
3868
  {
 
3869
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3870
    pthread_mutex_unlock(&LOCK_open);
 
3871
    goto err;
 
3872
  }
 
3873
 
 
3874
  /*
 
3875
    Data is copied. Now we:
 
3876
    1) Wait until all other threads close old version of table.
 
3877
    2) Close instances of table open by this thread and replace them
 
3878
       with exclusive name-locks.
 
3879
    3) Rename the old table to a temp name, rename the new one to the
 
3880
       old name.
 
3881
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
3882
       we reopen new version of table.
 
3883
    5) Write statement to the binary log.
 
3884
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
3885
       remove name-locks from list of open tables and table cache.
 
3886
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
3887
       call to remove name-locks from table cache and list of open table.
 
3888
  */
 
3889
 
 
3890
  session->set_proc_info("rename result table");
 
3891
 
 
3892
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
3893
 
 
3894
  my_casedn_str(files_charset_info, old_name);
 
3895
 
 
3896
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
3897
  session->close_data_files_and_morph_locks(db, table_name);
 
3898
 
 
3899
  error= 0;
 
3900
  save_old_db_type= old_db_type;
 
3901
 
 
3902
  /*
 
3903
    This leads to the storage engine (SE) not being notified for renames in
 
3904
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
3905
    more. If we have an intermediate table, then we notify the SE that
 
3906
    it should become the actual table. Later, we will recycle the old table.
 
3907
    However, in case of ALTER Table RENAME there might be no intermediate
 
3908
    table. This is when the old and new tables are compatible, according to
 
3909
    compare_table(). Then, we need one additional call to
 
3910
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
3911
    actual rename in the SE and the FRM is not touched. Note that, if the
 
3912
    table is renamed and the SE is also changed, then an intermediate table
 
3913
    is created and the additional call will not take place.
 
3914
  */
 
3915
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
 
3916
  {
 
3917
    error= 1;
 
3918
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3919
  }
 
3920
  else
 
3921
  {
 
3922
    if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
 
3923
    {
 
3924
      /* Try to get everything back. */
 
3925
      error= 1;
 
3926
      quick_rm_table(new_db_type, new_db, new_alias, false);
 
3927
      quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3928
      mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
 
3929
    }
 
3930
  }
 
3931
 
 
3932
  if (error)
 
3933
  {
 
3934
    /* This shouldn't happen. But let us play it safe. */
 
3935
    goto err_with_placeholders;
 
3936
  }
 
3937
 
 
3938
  quick_rm_table(old_db_type, db, old_name, true);
 
3939
 
 
3940
  pthread_mutex_unlock(&LOCK_open);
 
3941
 
 
3942
  session->set_proc_info("end");
 
3943
 
 
3944
  write_bin_log(session, true, session->query, session->query_length);
 
3945
 
 
3946
  if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
 
3947
  {
 
3948
    /*
 
3949
      For the alter table to be properly flushed to the logs, we
 
3950
      have to open the new table.  If not, we get a problem on server
 
3951
      shutdown. But we do not need to attach MERGE children.
 
3952
    */
 
3953
    char table_path[FN_REFLEN];
 
3954
    Table *t_table;
 
3955
    build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
 
3956
    t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
 
3957
    if (t_table)
 
3958
    {
 
3959
      t_table->intern_close_table();
 
3960
      free(t_table);
 
3961
    }
 
3962
    else
 
3963
      errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
 
3964
 
 
3965
    ha_flush_logs(old_db_type);
 
3966
  }
 
3967
  table_list->table= NULL;
 
3968
 
 
3969
end_temporary:
 
3970
  /*
 
3971
   * Field::store() may have called my_error().  If this is 
 
3972
   * the case, we must not send an ok packet, since 
 
3973
   * Diagnostics_area::is_set() will fail an assert.
 
3974
   */
 
3975
  if (! session->is_error())
 
3976
  {
 
3977
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
3978
            (ulong) (copied + deleted), (ulong) deleted,
 
3979
            (ulong) session->cuted_fields);
 
3980
    session->my_ok(copied + deleted, 0L, tmp_name);
 
3981
    session->some_tables_deleted=0;
 
3982
    return false;
 
3983
  }
 
3984
  else
 
3985
  {
 
3986
    /* my_error() was called.  Return true (which means error...) */
 
3987
    return true;
 
3988
  }
 
3989
 
 
3990
err1:
 
3991
  if (new_table)
 
3992
  {
 
3993
    /* close_temporary_table() frees the new_table pointer. */
 
3994
    session->close_temporary_table(new_table, true, true);
 
3995
  }
 
3996
  else
 
3997
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3998
 
 
3999
err:
 
4000
  /*
 
4001
    No default value was provided for a DATE/DATETIME field, the
 
4002
    current sql_mode doesn't allow the '0000-00-00' value and
 
4003
    the table to be altered isn't empty.
 
4004
    Report error here.
 
4005
  */
 
4006
  if (alter_info->error_if_not_empty && session->row_count)
 
4007
  {
 
4008
    const char *f_val= 0;
 
4009
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
4010
    switch (alter_info->datetime_field->sql_type)
 
4011
    {
 
4012
      case DRIZZLE_TYPE_DATE:
 
4013
        f_val= "0000-00-00";
 
4014
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
4015
        break;
 
4016
      case DRIZZLE_TYPE_DATETIME:
 
4017
        f_val= "0000-00-00 00:00:00";
 
4018
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
4019
        break;
 
4020
      default:
 
4021
        /* Shouldn't get here. */
 
4022
        assert(0);
 
4023
    }
 
4024
    bool save_abort_on_warning= session->abort_on_warning;
 
4025
    session->abort_on_warning= true;
 
4026
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
4027
                                 f_val, strlength(f_val), t_type,
 
4028
                                 alter_info->datetime_field->field_name);
 
4029
    session->abort_on_warning= save_abort_on_warning;
 
4030
  }
 
4031
  if (name_lock)
 
4032
  {
 
4033
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
 
4034
    session->unlink_open_table(name_lock);
 
4035
    pthread_mutex_unlock(&LOCK_open);
 
4036
  }
 
4037
  return true;
 
4038
 
 
4039
err_with_placeholders:
 
4040
  /*
 
4041
    An error happened while we were holding exclusive name-lock on table
 
4042
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
4043
    from list of open tables list and table cache.
 
4044
  */
 
4045
  session->unlink_open_table(table);
 
4046
  if (name_lock)
 
4047
    session->unlink_open_table(name_lock);
 
4048
  pthread_mutex_unlock(&LOCK_open);
 
4049
  return true;
 
4050
}
 
4051
/* mysql_alter_table */
 
4052
 
 
4053
static int
 
4054
copy_data_between_tables(Table *from,Table *to,
 
4055
                         List<CreateField> &create,
 
4056
                         bool ignore,
 
4057
                         uint32_t order_num, order_st *order,
 
4058
                         ha_rows *copied,
 
4059
                         ha_rows *deleted,
 
4060
                         enum enum_enable_or_disable keys_onoff,
 
4061
                         bool error_if_not_empty)
 
4062
{
 
4063
  int error;
 
4064
  CopyField *copy,*copy_end;
 
4065
  ulong found_count,delete_count;
 
4066
  Session *session= current_session;
 
4067
  uint32_t length= 0;
 
4068
  SORT_FIELD *sortorder;
 
4069
  READ_RECORD info;
 
4070
  TableList   tables;
 
4071
  List<Item>   fields;
 
4072
  List<Item>   all_fields;
 
4073
  ha_rows examined_rows;
 
4074
  bool auto_increment_field_copied= 0;
 
4075
  ulong save_sql_mode;
 
4076
  uint64_t prev_insert_id;
 
4077
 
 
4078
  /*
 
4079
    Turn off recovery logging since rollback of an alter table is to
 
4080
    delete the new table so there is no need to log the changes to it.
 
4081
 
 
4082
    This needs to be done before external_lock
 
4083
  */
 
4084
  error= ha_enable_transaction(session, false);
 
4085
  if (error)
 
4086
    return -1;
 
4087
 
 
4088
  if (!(copy= new CopyField[to->s->fields]))
 
4089
    return -1;                          /* purecov: inspected */
 
4090
 
 
4091
  if (to->file->ha_external_lock(session, F_WRLCK))
 
4092
    return -1;
 
4093
 
 
4094
  /* We need external lock before we can disable/enable keys */
 
4095
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
4096
 
 
4097
  /* We can abort alter table for any table type */
 
4098
  session->abort_on_warning= !ignore;
 
4099
 
 
4100
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
4101
  to->file->ha_start_bulk_insert(from->file->stats.records);
 
4102
 
 
4103
  save_sql_mode= session->variables.sql_mode;
 
4104
 
 
4105
  List_iterator<CreateField> it(create);
 
4106
  CreateField *def;
 
4107
  copy_end=copy;
 
4108
  for (Field **ptr=to->field ; *ptr ; ptr++)
 
4109
  {
 
4110
    def=it++;
 
4111
    if (def->field)
 
4112
    {
 
4113
      if (*ptr == to->next_number_field)
 
4114
        auto_increment_field_copied= true;
 
4115
 
 
4116
      (copy_end++)->set(*ptr,def->field,0);
 
4117
    }
 
4118
 
 
4119
  }
 
4120
 
 
4121
  found_count=delete_count=0;
 
4122
 
 
4123
  if (order)
 
4124
  {
 
4125
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
 
4126
    {
 
4127
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
4128
      snprintf(warn_buff, sizeof(warn_buff),
 
4129
               _("order_st BY ignored because there is a user-defined clustered "
 
4130
                 "index in the table '%-.192s'"),
 
4131
               from->s->table_name.str);
 
4132
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
4133
                   warn_buff);
 
4134
    }
 
4135
    else
 
4136
    {
 
4137
      from->sort.io_cache= new IO_CACHE;
 
4138
      memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
 
4139
 
 
4140
      memset(&tables, 0, sizeof(tables));
 
4141
      tables.table= from;
 
4142
      tables.alias= tables.table_name= from->s->table_name.str;
 
4143
      tables.db= from->s->db.str;
 
4144
      error= 1;
 
4145
 
 
4146
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
4147
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
4148
                      &tables, fields, all_fields, order) ||
 
4149
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
4150
          (from->sort.found_records= filesort(session, from, sortorder, length,
 
4151
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
4152
                                              1, &examined_rows)) ==
 
4153
          HA_POS_ERROR)
 
4154
        goto err;
 
4155
    }
 
4156
  };
 
4157
 
 
4158
  /* Tell handler that we have values for all columns in the to table */
 
4159
  to->use_all_columns();
 
4160
  init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
 
4161
  if (ignore)
 
4162
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
4163
  session->row_count= 0;
 
4164
  to->restoreRecordAsDefault();        // Create empty record
 
4165
  while (!(error=info.read_record(&info)))
 
4166
  {
 
4167
    if (session->killed)
 
4168
    {
 
4169
      session->send_kill_message();
 
4170
      error= 1;
 
4171
      break;
 
4172
    }
 
4173
    session->row_count++;
 
4174
    /* Return error if source table isn't empty. */
 
4175
    if (error_if_not_empty)
 
4176
    {
 
4177
      error= 1;
 
4178
      break;
 
4179
    }
 
4180
    if (to->next_number_field)
 
4181
    {
 
4182
      if (auto_increment_field_copied)
 
4183
        to->auto_increment_field_not_null= true;
 
4184
      else
 
4185
        to->next_number_field->reset();
 
4186
    }
 
4187
 
 
4188
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
4189
    {
 
4190
      copy_ptr->do_copy(copy_ptr);
 
4191
    }
 
4192
    prev_insert_id= to->file->next_insert_id;
 
4193
    error=to->file->ha_write_row(to->record[0]);
 
4194
    to->auto_increment_field_not_null= false;
 
4195
    if (error)
 
4196
    {
 
4197
      if (!ignore ||
 
4198
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
4199
      {
 
4200
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
4201
         {
 
4202
           uint32_t key_nr= to->file->get_dup_key(error);
 
4203
           if ((int) key_nr >= 0)
 
4204
           {
 
4205
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
4206
             if (key_nr == 0 &&
 
4207
                 (to->key_info[0].key_part[0].field->flags &
 
4208
                  AUTO_INCREMENT_FLAG))
 
4209
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
4210
             to->file->print_keydup_error(key_nr, err_msg);
 
4211
             break;
 
4212
           }
 
4213
         }
 
4214
 
 
4215
        to->file->print_error(error,MYF(0));
 
4216
        break;
 
4217
      }
 
4218
      to->file->restore_auto_increment(prev_insert_id);
 
4219
      delete_count++;
 
4220
    }
 
4221
    else
 
4222
      found_count++;
 
4223
  }
 
4224
  end_read_record(&info);
 
4225
  from->free_io_cache();
 
4226
  delete [] copy;                               // This is never 0
 
4227
 
 
4228
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
4229
  {
 
4230
    to->file->print_error(my_errno,MYF(0));
 
4231
    error=1;
 
4232
  }
 
4233
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
4234
 
 
4235
  if (ha_enable_transaction(session, true))
 
4236
  {
 
4237
    error= 1;
 
4238
    goto err;
 
4239
  }
 
4240
 
 
4241
  /*
 
4242
    Ensure that the new table is saved properly to disk so that we
 
4243
    can do a rename
 
4244
  */
 
4245
  if (ha_autocommit_or_rollback(session, 0))
 
4246
    error=1;
 
4247
  if (! session->endActiveTransaction())
 
4248
    error=1;
 
4249
 
 
4250
 err:
 
4251
  session->variables.sql_mode= save_sql_mode;
 
4252
  session->abort_on_warning= 0;
 
4253
  from->free_io_cache();
 
4254
  *copied= found_count;
 
4255
  *deleted=delete_count;
 
4256
  to->file->ha_release_auto_increment();
 
4257
  if (to->file->ha_external_lock(session,F_UNLCK))
 
4258
    error=1;
 
4259
  return(error > 0 ? -1 : 0);
 
4260
}
 
4261
 
 
4262
 
 
4263
/*
 
4264
  Recreates tables by calling mysql_alter_table().
 
4265
 
 
4266
  SYNOPSIS
 
4267
    mysql_recreate_table()
 
4268
    session                     Thread handler
 
4269
    tables              Tables to recreate
 
4270
 
 
4271
 RETURN
 
4272
    Like mysql_alter_table().
 
4273
*/
 
4274
bool mysql_recreate_table(Session *session, TableList *table_list)
 
4275
{
 
4276
  HA_CREATE_INFO create_info;
 
4277
  Alter_info alter_info;
 
4278
 
 
4279
  assert(!table_list->next_global);
 
4280
  /*
 
4281
    table_list->table has been closed and freed. Do not reference
 
4282
    uninitialized data. open_tables() could fail.
 
4283
  */
 
4284
  table_list->table= NULL;
 
4285
 
 
4286
  memset(&create_info, 0, sizeof(create_info));
 
4287
  create_info.row_type=ROW_TYPE_NOT_USED;
 
4288
  create_info.default_table_charset=default_charset_info;
 
4289
  /* Force alter table to recreate table */
 
4290
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
4291
  alter_info.flags.set(ALTER_RECREATE);
 
4292
  return(mysql_alter_table(session, NULL, NULL, &create_info,
 
4293
                                table_list, &alter_info, 0,
 
4294
                                (order_st *) 0, 0));
2268
4295
}
2269
4296
 
2270
4297
 
2271
4298
bool mysql_checksum_table(Session *session, TableList *tables,
2272
 
                          HA_CHECK_OPT *)
 
4299
                          HA_CHECK_OPT *check_opt)
2273
4300
{
2274
4301
  TableList *table;
2275
4302
  List<Item> field_list;
2276
4303
  Item *item;
 
4304
  Protocol *protocol= session->protocol;
2277
4305
 
2278
4306
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2279
4307
  item->maybe_null= 1;
2280
4308
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2281
4309
                                          MY_INT64_NUM_DECIMAL_DIGITS));
2282
4310
  item->maybe_null= 1;
2283
 
  if (session->client->sendFields(&field_list))
2284
 
    return true;
 
4311
  if (protocol->sendFields(&field_list,
 
4312
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
4313
    return(true);
2285
4314
 
2286
4315
  /* Open one table after the other to keep lock time as short as possible. */
2287
4316
  for (table= tables; table; table= table->next_local)
2289
4318
    char table_name[NAME_LEN*2+2];
2290
4319
    Table *t;
2291
4320
 
2292
 
    snprintf(table_name, sizeof(table_name), "%s.%s",table->db,table->table_name);
 
4321
    sprintf(table_name,"%s.%s",table->db,table->table_name);
2293
4322
 
2294
4323
    t= table->table= session->openTableLock(table, TL_READ);
2295
4324
    session->clear_error();                     // these errors shouldn't get client
2296
4325
 
2297
 
    session->client->store(table_name);
 
4326
    protocol->prepareForResend();
 
4327
    protocol->store(table_name);
2298
4328
 
2299
4329
    if (!t)
2300
4330
    {
2301
4331
      /* Table didn't exist */
2302
 
      session->client->store();
 
4332
      protocol->store();
2303
4333
      session->clear_error();
2304
4334
    }
2305
4335
    else
2306
4336
    {
2307
 
      /**
2308
 
        @note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2309
 
      */
2310
 
      if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
2311
 
      {
2312
 
        session->client->store((uint64_t)t->cursor->checksum());
2313
 
      }
 
4337
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
4338
          !(check_opt->flags & T_EXTEND))
 
4339
        protocol->store((uint64_t)t->file->checksum());
 
4340
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
4341
               (check_opt->flags & T_QUICK))
 
4342
        protocol->store();
2314
4343
      else
2315
4344
      {
2316
4345
        /* calculating table's checksum */
2317
 
        internal::ha_checksum crc= 0;
 
4346
        ha_checksum crc= 0;
2318
4347
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
2319
4348
 
2320
4349
        t->use_all_columns();
2321
4350
 
2322
 
        if (t->cursor->ha_rnd_init(1))
2323
 
          session->client->store();
 
4351
        if (t->file->ha_rnd_init(1))
 
4352
          protocol->store();
2324
4353
        else
2325
4354
        {
2326
4355
          for (;;)
2327
4356
          {
2328
 
            internal::ha_checksum row_crc= 0;
2329
 
            int error= t->cursor->rnd_next(t->record[0]);
 
4357
            ha_checksum row_crc= 0;
 
4358
            int error= t->file->rnd_next(t->record[0]);
2330
4359
            if (unlikely(error))
2331
4360
            {
2332
4361
              if (error == HA_ERR_RECORD_DELETED)
2340
4369
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2341
4370
                t->record[0][0] |= 1;
2342
4371
 
2343
 
              row_crc= internal::my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
4372
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2344
4373
            }
2345
4374
 
2346
4375
            for (uint32_t i= 0; i < t->s->fields; i++ )
2351
4380
              {
2352
4381
                String tmp;
2353
4382
                f->val_str(&tmp);
2354
 
                row_crc= internal::my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
4383
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2355
4384
              }
2356
4385
              else
2357
 
                row_crc= internal::my_checksum(row_crc, f->ptr,
 
4386
                row_crc= my_checksum(row_crc, f->ptr,
2358
4387
                                     f->pack_length());
2359
4388
            }
2360
4389
 
2361
4390
            crc+= row_crc;
2362
4391
          }
2363
 
          session->client->store((uint64_t)crc);
2364
 
          t->cursor->ha_rnd_end();
 
4392
          protocol->store((uint64_t)crc);
 
4393
          t->file->ha_rnd_end();
2365
4394
        }
2366
4395
      }
2367
4396
      session->clear_error();
2368
4397
      session->close_thread_tables();
2369
4398
      table->table=0;                           // For query cache
2370
4399
    }
2371
 
    if (session->client->flush())
 
4400
    if (protocol->write())
2372
4401
      goto err;
2373
4402
  }
2374
4403
 
2382
4411
  return(true);
2383
4412
}
2384
4413
 
2385
 
} /* namespace drizzled */
 
4414
static bool check_engine(Session *session, const char *table_name,
 
4415
                         HA_CREATE_INFO *create_info)
 
4416
{
 
4417
  StorageEngine **new_engine= &create_info->db_type;
 
4418
  StorageEngine *req_engine= *new_engine;
 
4419
  if (!req_engine->is_enabled())
 
4420
  {
 
4421
    string engine_name= req_engine->getName();
 
4422
    my_error(ER_FEATURE_DISABLED,MYF(0),
 
4423
             engine_name.c_str(), engine_name.c_str());
 
4424
             
 
4425
    return true;
 
4426
  }
 
4427
 
 
4428
  if (req_engine && req_engine != *new_engine)
 
4429
  {
 
4430
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
4431
                       ER_WARN_USING_OTHER_HANDLER,
 
4432
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
4433
                       ha_resolve_storage_engine_name(*new_engine).c_str(),
 
4434
                       table_name);
 
4435
  }
 
4436
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
4437
      (*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
 
4438
  {
 
4439
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
4440
    {
 
4441
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
4442
               ha_resolve_storage_engine_name(*new_engine).c_str(),
 
4443
               "TEMPORARY");
 
4444
      *new_engine= 0;
 
4445
      return true;
 
4446
    }
 
4447
    *new_engine= myisam_engine;
 
4448
  }
 
4449
  if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
4450
     && (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
 
4451
  {
 
4452
    my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
4453
             ha_resolve_storage_engine_name(*new_engine).c_str(),
 
4454
             "non-TEMPORARY");
 
4455
    *new_engine= 0;
 
4456
    return true;
 
4457
  }
 
4458
 
 
4459
  return false;
 
4460
}