~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Jay Pipes
  • Date: 2009-02-21 16:00:06 UTC
  • mto: (907.1.1 trunk-with-temporal)
  • mto: This revision was merged to the branch mainline in revision 908.
  • Revision ID: jpipes@serialcoder-20090221160006-vnk3wt4qbcz62eru
Removes the TIME column type and related time functions.

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"
19
 
#include <plugin/myisam/myisam.h>
 
18
#include <drizzled/server_includes.h>
 
19
#include <storage/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"
37
 
#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
 
 
49
 
#include <algorithm>
50
 
#include <sstream>
 
34
#include <drizzled/replicator.h>
51
35
 
52
36
using namespace std;
53
37
 
54
 
namespace drizzled
55
 
{
56
 
 
57
 
extern plugin::StorageEngine *myisam_engine;
58
 
extern pid_t current_pid;
 
38
extern HASH lock_db_cache;
 
39
 
 
40
int creating_table= 0;        // How many mysql_create_table are running
 
41
 
59
42
 
60
43
bool is_primary_key(KEY *key_info)
61
44
{
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);
77
 
 
78
 
static bool prepare_blob_field(Session *session, CreateField *sql_field);
79
 
 
80
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
 
60
static int copy_data_between_tables(Table *from,Table *to,
 
61
                                    List<Create_field> &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);
 
66
 
 
67
static bool prepare_blob_field(Session *session, Create_field *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);
 
80
 
 
81
static void set_table_default_charset(Session *session,
 
82
                                      HA_CREATE_INFO *create_info, char *db)
81
83
{
82
84
  /*
83
85
    If the table character set was not given explicitly,
84
86
    let's fetch the database default character set and
85
87
    apply it to the table.
86
88
  */
87
 
  SchemaIdentifier identifier(db);
88
 
  if (create_info->default_table_charset == NULL)
89
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
89
  if (!create_info->default_table_charset)
 
90
  {
 
91
    HA_CREATE_INFO db_info;
 
92
 
 
93
    load_db_opt_by_name(session, db, &db_info);
 
94
 
 
95
    create_info->default_table_charset= db_info.default_table_charset;
 
96
  }
 
97
}
 
98
 
 
99
/*
 
100
  Translate a file name to a table name (WL #1324).
 
101
 
 
102
  SYNOPSIS
 
103
    filename_to_tablename()
 
104
      from                      The file name in my_charset_filename.
 
105
      to                OUT     The table name in system_charset_info.
 
106
      to_length                 The size of the table name buffer.
 
107
 
 
108
  RETURN
 
109
    Table name length.
 
110
*/
 
111
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
112
{
 
113
  uint32_t errors;
 
114
  uint32_t res;
 
115
 
 
116
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
117
  {
 
118
    /* Temporary table name. */
 
119
    res= strlen(strncpy(to, from, to_length));
 
120
  }
 
121
  else
 
122
  {
 
123
    res= strconvert(&my_charset_filename, from,
 
124
                    system_charset_info,  to, to_length, &errors);
 
125
    if (errors) // Old 5.0 name
 
126
    {
 
127
      strcpy(to, MYSQL50_TABLE_NAME_PREFIX);
 
128
      strncat(to, from, to_length-MYSQL50_TABLE_NAME_PREFIX_LENGTH-1);
 
129
      res= strlen(to);
 
130
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid (old?) table or database name '%s'"), from);
 
131
    }
 
132
  }
 
133
 
 
134
  return(res);
 
135
}
 
136
 
 
137
 
 
138
/*
 
139
  Translate a table name to a file name (WL #1324).
 
140
 
 
141
  SYNOPSIS
 
142
    tablename_to_filename()
 
143
      from                      The table name in system_charset_info.
 
144
      to                OUT     The file name in my_charset_filename.
 
145
      to_length                 The size of the file name buffer.
 
146
 
 
147
  RETURN
 
148
    File name length.
 
149
*/
 
150
uint32_t tablename_to_filename(const char *from, char *to, uint32_t to_length)
 
151
{
 
152
  uint32_t errors, length;
 
153
 
 
154
  if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
 
155
                                 MYSQL50_TABLE_NAME_PREFIX_LENGTH))
 
156
    return((uint32_t) (strncpy(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
 
157
                           to_length-1) -
 
158
                           (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
 
159
  length= strconvert(system_charset_info, from,
 
160
                     &my_charset_filename, to, to_length, &errors);
 
161
  if (check_if_legal_tablename(to) &&
 
162
      length + 4 < to_length)
 
163
  {
 
164
    memcpy(to + length, "@@@", 4);
 
165
    length+= 3;
 
166
  }
 
167
  return(length);
 
168
}
 
169
 
 
170
 
 
171
/*
 
172
  Creates path to a file: drizzle_data_dir/db/table.ext
 
173
 
 
174
  SYNOPSIS
 
175
   build_table_filename()
 
176
     buff                       Where to write result in my_charset_filename.
 
177
                                This may be the same as table_name.
 
178
     bufflen                    buff size
 
179
     db                         Database name in system_charset_info.
 
180
     table_name                 Table name in system_charset_info.
 
181
     ext                        File extension.
 
182
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
183
                                table_name is temporary, do not change.
 
184
 
 
185
  NOTES
 
186
 
 
187
    Uses database and table name, and extension to create
 
188
    a file name in drizzle_data_dir. Database and table
 
189
    names are converted from system_charset_info into "fscs".
 
190
    Unless flags indicate a temporary table name.
 
191
    'db' is always converted.
 
192
    'ext' is not converted.
 
193
 
 
194
    The conversion suppression is required for ALTER Table. This
 
195
    statement creates intermediate tables. These are regular
 
196
    (non-temporary) tables with a temporary name. Their path names must
 
197
    be derivable from the table name. So we cannot use
 
198
    build_tmptable_filename() for them.
 
199
 
 
200
  RETURN
 
201
    path length on success, 0 on failure
 
202
*/
 
203
 
 
204
uint32_t build_table_filename(char *buff, size_t bufflen, const char *db,
 
205
                          const char *table_name, const char *ext, uint32_t flags)
 
206
{
 
207
  string table_path;
 
208
  char dbbuff[FN_REFLEN];
 
209
  char tbbuff[FN_REFLEN];
 
210
  int rootdir_len= strlen(FN_ROOTDIR);
 
211
 
 
212
  if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
213
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
214
  else
 
215
    tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
216
 
 
217
  tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
218
  table_path= drizzle_data_home;
 
219
  int without_rootdir= table_path.length()-rootdir_len;
 
220
 
 
221
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
222
  if (without_rootdir >= 0)
 
223
  {
 
224
    char *tmp= (char*)table_path.c_str()+without_rootdir;
 
225
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
226
      table_path.append(FN_ROOTDIR);
 
227
  }
 
228
 
 
229
  table_path.append(dbbuff);
 
230
  table_path.append(FN_ROOTDIR);
 
231
#ifdef USE_SYMDIR
 
232
  table_path.clear();
 
233
#endif
 
234
  table_path.append(tbbuff);
 
235
  table_path.append(ext);
 
236
 
 
237
  if (bufflen < table_path.length())
 
238
    return 0;
 
239
 
 
240
  strcpy(buff, table_path.c_str());
 
241
  return table_path.length();
 
242
}
 
243
 
 
244
 
 
245
/*
 
246
  Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
 
247
 
 
248
  SYNOPSIS
 
249
   build_tmptable_filename()
 
250
     session                    The thread handle.
 
251
     buff                       Where to write result in my_charset_filename.
 
252
     bufflen                    buff size
 
253
 
 
254
  NOTES
 
255
 
 
256
    Uses current_pid, thread_id, and tmp_table counter to create
 
257
    a file name in drizzle_tmpdir.
 
258
 
 
259
  RETURN
 
260
    path length on success, 0 on failure
 
261
*/
 
262
 
 
263
uint32_t build_tmptable_filename(Session* session, char *buff, size_t bufflen)
 
264
{
 
265
  uint32_t length;
 
266
  ostringstream path_str, post_tmpdir_str;
 
267
  string tmp;
 
268
 
 
269
  path_str << drizzle_tmpdir;
 
270
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
271
  post_tmpdir_str << session->thread_id << session->tmp_table++ << reg_ext;
 
272
  tmp= post_tmpdir_str.str();
 
273
 
 
274
  if (lower_case_table_names)
 
275
    transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
276
 
 
277
  path_str << tmp;
 
278
 
 
279
  if (bufflen < path_str.str().length())
 
280
    length= 0;
 
281
  else
 
282
    length= unpack_filename(buff, path_str.str().c_str());
 
283
 
 
284
  return length;
90
285
}
91
286
 
92
287
/*
93
288
  SYNOPSIS
94
289
    write_bin_log()
95
290
    session                           Thread object
 
291
    clear_error                   is clear_error to be called
96
292
    query                         Query to log
97
293
    query_length                  Length of query
98
294
 
101
297
 
102
298
  DESCRIPTION
103
299
    Write the binlog if open, routine used in multiple places in this
104
 
    cursor
 
300
    file
105
301
*/
106
302
 
107
 
void write_bin_log(Session *session,
108
 
                   char const *query)
 
303
void write_bin_log(Session *session, bool,
 
304
                   char const *query, size_t query_length)
109
305
{
110
 
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(session, query);
 
306
  (void)replicator_statement(session, query, query_length);
112
307
}
113
308
 
114
309
 
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)
 
310
/*
 
311
 delete (drop) tables.
 
312
 
 
313
  SYNOPSIS
 
314
   mysql_rm_table()
 
315
   session                      Thread handle
 
316
   tables               List of tables to delete
 
317
   if_exists            If 1, don't give error if one table doesn't exists
 
318
 
 
319
  NOTES
 
320
    Will delete all tables that can be deleted and give a compact error
 
321
    messages for tables that could not be deleted.
 
322
    If a table is in use, we will wait for all users to free the table
 
323
    before dropping it
 
324
 
 
325
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
326
    not if under LOCK TABLES.
 
327
 
 
328
  RETURN
 
329
    false OK.  In this case ok packet is sent to user
 
330
    true  Error
 
331
 
 
332
*/
 
333
 
 
334
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
117
335
{
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);
 
336
  bool error, need_start_waiting= false;
 
337
 
 
338
  if (tables && tables->schema_table)
 
339
  {
 
340
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
341
    return(true);
 
342
  }
 
343
 
 
344
  /* mark for close and remove all cached entries */
 
345
 
 
346
  if (!drop_temporary)
 
347
  {
 
348
    if (!session->locked_tables &&
 
349
        !(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
350
      return(true);
 
351
  }
 
352
 
 
353
  /*
 
354
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
355
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
356
    close their tables. This would make a pretty deadlock.
 
357
  */
 
358
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, 0);
 
359
 
 
360
  if (need_start_waiting)
 
361
    start_waiting_global_read_lock(session);
 
362
 
 
363
  if (error)
 
364
    return(true);
 
365
  session->my_ok();
 
366
  return(false);
136
367
}
137
368
 
138
369
/*
140
371
 
141
372
  SYNOPSIS
142
373
    mysql_rm_table_part2()
143
 
    session                     Thread Cursor
 
374
    session                     Thread handler
144
375
    tables              Tables to drop
145
376
    if_exists           If set, don't give an error if table doesn't exists.
146
377
                        In this case we give an warning of level 'NOTE'
147
378
    drop_temporary      Only drop temporary tables
 
379
    drop_view           Allow to delete VIEW .frm
 
380
    dont_log_query      Don't write query to log files. This will also not
 
381
                        generate warnings if the handler files doesn't exists
148
382
 
149
383
  TODO:
150
384
    When logging to the binary log, we should log
163
397
*/
164
398
 
165
399
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
166
 
                         bool drop_temporary)
 
400
                         bool drop_temporary, bool dont_log_query)
167
401
{
168
402
  TableList *table;
 
403
  char path[FN_REFLEN], *alias;
 
404
  uint32_t path_length= 0;
169
405
  String wrong_tables;
170
406
  int error= 0;
171
 
  bool foreign_key_error= false;
172
 
 
173
 
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
407
  int non_temp_tables_count= 0;
 
408
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
 
409
  String built_query;
 
410
 
 
411
  if (!dont_log_query)
 
412
  {
 
413
    built_query.set_charset(system_charset_info);
 
414
    if (if_exists)
 
415
      built_query.append("DROP Table IF EXISTS ");
 
416
    else
 
417
      built_query.append("DROP Table ");
 
418
  }
 
419
 
 
420
  mysql_ha_rm_tables(session, tables, false);
 
421
 
 
422
  pthread_mutex_lock(&LOCK_open);
174
423
 
175
424
  /*
176
425
    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
 
426
    .frm file to find if the table is a normal table (not view) and what
178
427
    engine to use.
179
428
  */
180
429
 
181
430
  for (table= tables; table; table= table->next_local)
182
431
  {
183
 
    TableIdentifier identifier(table->db, table->table_name);
184
 
    TableShare *share;
 
432
    TABLE_SHARE *share;
185
433
    table->db_type= NULL;
186
 
 
187
 
    if ((share= TableShare::getShare(identifier)))
188
 
    {
 
434
    if ((share= get_cached_table_share(table->db, table->table_name)))
189
435
      table->db_type= share->db_type();
190
 
    }
191
436
  }
192
437
 
193
 
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
438
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
194
439
  {
195
440
    pthread_mutex_unlock(&LOCK_open);
196
 
    return 1;
 
441
    return(1);
197
442
  }
198
443
 
199
444
  /* Don't give warnings for not found errors, as we already generate notes */
202
447
  for (table= tables; table; table= table->next_local)
203
448
  {
204
449
    char *db=table->db;
 
450
    handlerton *table_type;
205
451
 
206
 
    error= session->drop_temporary_table(table);
 
452
    error= drop_temporary_table(session, table);
207
453
 
208
454
    switch (error) {
209
455
    case  0:
210
456
      // removed temporary table
 
457
      tmp_table_deleted= 1;
211
458
      continue;
212
459
    case -1:
213
460
      error= 1;
217
464
      error= 0;
218
465
    }
219
466
 
220
 
    if (drop_temporary == false)
 
467
    /*
 
468
      If row-based replication is used and the table is not a
 
469
      temporary table, we add the table name to the drop statement
 
470
      being built.  The string always end in a comma and the comma
 
471
      will be chopped off before being written to the binary log.
 
472
      */
 
473
    if (!dont_log_query)
 
474
    {
 
475
      non_temp_tables_count++;
 
476
      /*
 
477
        Don't write the database name if it is the current one (or if
 
478
        session->db is NULL).
 
479
      */
 
480
      built_query.append("`");
 
481
      if (session->db == NULL || strcmp(db,session->db) != 0)
 
482
      {
 
483
        built_query.append(db);
 
484
        built_query.append("`.`");
 
485
      }
 
486
 
 
487
      built_query.append(table->table_name);
 
488
      built_query.append("`,");
 
489
    }
 
490
 
 
491
    table_type= table->db_type;
 
492
    if (!drop_temporary)
221
493
    {
222
494
      Table *locked_table;
223
495
      abort_locked_tables(session, db, table->table_name);
236
508
        error= -1;
237
509
        goto err_with_placeholders;
238
510
      }
 
511
      alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
 
512
      /* remove .frm file and engine files */
 
513
      path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
514
                                        table->internal_tmp_table ?
 
515
                                        FN_IS_TMP : 0);
239
516
    }
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))
 
517
    if (drop_temporary ||
 
518
        ((table_type == NULL && (access(path, F_OK))))
 
519
        )
243
520
    {
244
521
      // Table was not found on disk and table can't be created from engine
245
522
      if (if_exists)
251
528
    }
252
529
    else
253
530
    {
254
 
      error= plugin::StorageEngine::dropTable(*session, identifier);
255
 
 
256
 
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
531
      char *end;
 
532
      // Remove extension for delete
 
533
      *(end= path + path_length - reg_ext_length)= '\0';
 
534
      error= ha_delete_table(session, path, db, table->table_name,
 
535
                             !dont_log_query);
 
536
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
 
537
          if_exists)
257
538
      {
258
 
        error= 0;
 
539
        error= 0;
259
540
        session->clear_error();
260
541
      }
261
 
 
262
542
      if (error == HA_ERR_ROW_IS_REFERENCED)
263
543
      {
264
544
        /* 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
 
 
 
545
        foreign_key_error=1;
 
546
      }
 
547
      if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
 
548
      {
 
549
        int new_error;
 
550
 
 
551
        /* for some weird-ass reason, we ignore the return code here
 
552
           and things work. */
 
553
        delete_table_proto_file(path);
 
554
 
 
555
        /* Delete the table definition file */
 
556
        strcpy(end,reg_ext);
 
557
        if (!(new_error=my_delete(path,MYF(MY_WME))))
 
558
        {
 
559
          some_tables_deleted=1;
 
560
          new_error= 0;
 
561
        }
 
562
        error|= new_error;
 
563
      }
 
564
    }
275
565
    if (error)
276
566
    {
277
567
      if (wrong_tables.length())
284
574
    on the table name.
285
575
  */
286
576
  pthread_mutex_unlock(&LOCK_open);
 
577
  session->thread_specific_used|= tmp_table_deleted;
287
578
  error= 0;
288
 
 
289
579
  if (wrong_tables.length())
290
580
  {
291
 
    if (not foreign_key_error)
292
 
    {
 
581
    if (!foreign_key_error)
293
582
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
294
583
                      wrong_tables.c_ptr());
295
 
    }
296
584
    else
297
585
    {
298
586
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
300
588
    error= 1;
301
589
  }
302
590
 
303
 
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
 
591
  if (some_tables_deleted || tmp_table_deleted || !error)
 
592
  {
 
593
    if (!dont_log_query)
 
594
    {
 
595
      if ((non_temp_tables_count > 0 && !tmp_table_deleted))
 
596
      {
 
597
        /*
 
598
          In this case, we are either using statement-based
 
599
          replication or using row-based replication but have only
 
600
          deleted one or more non-temporary tables (and no temporary
 
601
          tables).  In this case, we can write the original query into
 
602
          the binary log.
 
603
         */
 
604
        write_bin_log(session, !error, session->query, session->query_length);
 
605
      }
 
606
      else if (non_temp_tables_count > 0 &&
 
607
               tmp_table_deleted)
 
608
      {
 
609
        /*
 
610
          In this case we have deleted both temporary and
 
611
          non-temporary tables, so:
 
612
          - since we have deleted a non-temporary table we have to
 
613
            binlog the statement, but
 
614
          - since we have deleted a temporary table we cannot binlog
 
615
            the statement (since the table has not been created on the
 
616
            slave, this might cause the slave to stop).
304
617
 
 
618
          Instead, we write a built statement, only containing the
 
619
          non-temporary tables, to the binary log
 
620
        */
 
621
        built_query.chop();                  // Chop of the last comma
 
622
        built_query.append(" /* generated by server */");
 
623
        write_bin_log(session, !error, built_query.ptr(), built_query.length());
 
624
      }
 
625
      /*
 
626
        The remaining cases are:
 
627
        - no tables where deleted and
 
628
        - only temporary tables where deleted and row-based
 
629
          replication is used.
 
630
        In both these cases, nothing should be written to the binary
 
631
        log.
 
632
      */
 
633
    }
 
634
  }
 
635
  pthread_mutex_lock(&LOCK_open);
305
636
err_with_placeholders:
306
 
  unlock_table_names(tables, NULL);
 
637
  unlock_table_names(session, tables, (TableList*) 0);
307
638
  pthread_mutex_unlock(&LOCK_open);
308
639
  session->no_warnings_for_error= 0;
309
 
 
310
 
  return error;
 
640
  return(error);
311
641
}
312
642
 
313
643
 
316
646
 
317
647
  SYNOPSIS
318
648
    quick_rm_table()
319
 
      base                      The plugin::StorageEngine handle.
 
649
      base                      The handlerton handle.
320
650
      db                        The database name.
321
651
      table_name                The table name.
322
 
      is_tmp                    If the table is temp.
 
652
      flags                     flags for build_table_filename().
323
653
 
324
654
  RETURN
325
655
    0           OK
326
656
    != 0        Error
327
657
*/
328
 
bool quick_rm_table(Session& session,
329
 
                    TableIdentifier &identifier)
 
658
 
 
659
bool quick_rm_table(handlerton *,const char *db,
 
660
                    const char *table_name, uint32_t flags)
330
661
{
331
 
  return (plugin::StorageEngine::dropTable(session, identifier));
 
662
  char path[FN_REFLEN];
 
663
  bool error= 0;
 
664
 
 
665
  uint32_t path_length= build_table_filename(path, sizeof(path),
 
666
                                         db, table_name, reg_ext, flags);
 
667
  if (my_delete(path,MYF(0)))
 
668
    error= 1; /* purecov: inspected */
 
669
 
 
670
  path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
 
671
 
 
672
  error|= delete_table_proto_file(path);
 
673
 
 
674
  return(ha_delete_table(current_session, path, db, table_name, 0) ||
 
675
              error);
332
676
}
333
677
 
334
678
/*
396
740
    1             Error
397
741
*/
398
742
 
399
 
static bool check_duplicates_in_interval(const char *set_or_name,
400
 
                                         const char *name, TYPELIB *typelib,
401
 
                                         const CHARSET_INFO * const cs,
402
 
                                         unsigned int *dup_val_count)
 
743
bool check_duplicates_in_interval(const char *set_or_name,
 
744
                                  const char *name, TYPELIB *typelib,
 
745
                                  const CHARSET_INFO * const cs, unsigned int *dup_val_count)
403
746
{
404
747
  TYPELIB tmp= *typelib;
405
748
  const char **cur_value= typelib->type_names;
440
783
  RETURN VALUES
441
784
    void
442
785
*/
443
 
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
444
 
                                       TYPELIB *interval,
445
 
                                       uint32_t *max_length,
446
 
                                       uint32_t *tot_length)
 
786
void calculate_interval_lengths(const CHARSET_INFO * const cs, TYPELIB *interval,
 
787
                                uint32_t *max_length, uint32_t *tot_length)
447
788
{
448
789
  const char **pos;
449
790
  uint32_t *len;
457
798
  }
458
799
}
459
800
 
 
801
 
460
802
/*
461
803
  Prepare a create_table instance for packing
462
804
 
465
807
    sql_field     field to prepare for packing
466
808
    blob_columns  count for BLOBs
467
809
    timestamps    count for timestamps
 
810
    table_flags   table flags
468
811
 
469
812
  DESCRIPTION
470
 
    This function prepares a CreateField instance.
 
813
    This function prepares a Create_field instance.
471
814
    Fields such as pack_flag are valid after this call.
472
815
 
473
816
  RETURN VALUES
474
817
   0    ok
475
818
   1    Error
476
819
*/
477
 
int prepare_create_field(CreateField *sql_field,
 
820
 
 
821
int prepare_create_field(Create_field *sql_field,
478
822
                         uint32_t *blob_columns,
479
 
                         int *timestamps,
480
 
                         int *timestamps_with_niladic)
 
823
                         int *timestamps, int *timestamps_with_niladic,
 
824
                         int64_t )
481
825
{
482
826
  unsigned int dup_val_count;
483
827
 
489
833
 
490
834
  switch (sql_field->sql_type) {
491
835
  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
 
836
    sql_field->pack_flag=FIELDFLAG_BLOB |
 
837
      pack_length_to_packflag(sql_field->pack_length -
 
838
                              portable_sizeof_char_ptr);
 
839
    if (sql_field->charset->state & MY_CS_BINSORT)
 
840
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
841
    sql_field->length=8;                        // Unireg field length
494
842
    (*blob_columns)++;
495
843
    break;
496
844
  case DRIZZLE_TYPE_VARCHAR:
497
845
    sql_field->pack_flag=0;
 
846
    if (sql_field->charset->state & MY_CS_BINSORT)
 
847
      sql_field->pack_flag|=FIELDFLAG_BINARY;
498
848
    break;
499
849
  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))
506
 
      return 1;
 
850
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
851
      FIELDFLAG_INTERVAL;
 
852
    if (sql_field->charset->state & MY_CS_BINSORT)
 
853
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
854
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
 
855
                                 sql_field->interval,
 
856
                                     sql_field->charset, &dup_val_count))
 
857
      return(1);
507
858
    break;
508
859
  case DRIZZLE_TYPE_DATE:  // Rest of string types
509
860
  case DRIZZLE_TYPE_DATETIME:
510
861
  case DRIZZLE_TYPE_NULL:
511
862
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
512
863
    break;
513
 
  case DRIZZLE_TYPE_DECIMAL:
514
 
    sql_field->pack_flag= 0;
 
864
  case DRIZZLE_TYPE_NEWDECIMAL:
 
865
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
866
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
867
                           FIELDFLAG_DECIMAL) |
 
868
                          (sql_field->flags & DECIMAL_FLAG ?  FIELDFLAG_DECIMAL_POSITION : 0) |
 
869
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
515
870
    break;
516
871
  case DRIZZLE_TYPE_TIMESTAMP:
517
872
    /* We should replace old TIMESTAMP fields with their newer analogs */
531
886
    (*timestamps)++;
532
887
    /* fall-through */
533
888
  default:
534
 
    sql_field->pack_flag=(0 |
535
 
                          f_settype((uint32_t) sql_field->sql_type));
 
889
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
890
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
891
                           FIELDFLAG_DECIMAL) |
 
892
                          f_settype((uint32_t) sql_field->sql_type) |
 
893
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
536
894
    break;
537
895
  }
538
 
  return 0;
 
896
  if (!(sql_field->flags & NOT_NULL_FLAG) ||
 
897
      (sql_field->vcol_info)) /* Make virtual columns always allow NULL values */
 
898
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
 
899
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
 
900
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
 
901
  return(0);
539
902
}
540
903
 
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)
 
904
/*
 
905
  Preparation for table creation
 
906
 
 
907
  SYNOPSIS
 
908
    mysql_prepare_create_table()
 
909
      session                       Thread object.
 
910
      create_info               Create information (like MAX_ROWS).
 
911
      alter_info                List of columns and indexes to create
 
912
      tmp_table                 If a temporary table is to be created.
 
913
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
 
914
      file                      The handler for the new table.
 
915
      key_info_buffer     OUT   An array of KEY structs for the indexes.
 
916
      key_count           OUT   The number of elements in the array.
 
917
      select_field_count        The number of fields coming from a select table.
 
918
 
 
919
  DESCRIPTION
 
920
    Prepares the table and key structures for table creation.
 
921
 
 
922
  NOTES
 
923
    sets create_info->varchar if the table has a varchar
 
924
 
 
925
  RETURN VALUES
 
926
    false    OK
 
927
    true     error
 
928
*/
 
929
 
 
930
static int
 
931
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
 
932
                           Alter_info *alter_info,
 
933
                           bool tmp_table,
 
934
                               uint32_t *db_options,
 
935
                               handler *file, KEY **key_info_buffer,
 
936
                               uint32_t *key_count, int select_field_count)
550
937
{
551
938
  const char    *key_name;
552
 
  CreateField   *sql_field,*dup_field;
 
939
  Create_field  *sql_field,*dup_field;
553
940
  uint          field,null_fields,blob_columns,max_key_length;
554
941
  ulong         record_offset= 0;
555
942
  KEY           *key_info;
557
944
  int           timestamps= 0, timestamps_with_niladic= 0;
558
945
  int           field_no,dup_no;
559
946
  int           select_field_pos,auto_increment=0;
560
 
  List_iterator<CreateField> it(alter_info->create_list);
561
 
  List_iterator<CreateField> it2(alter_info->create_list);
 
947
  List_iterator<Create_field> it(alter_info->create_list);
 
948
  List_iterator<Create_field> it2(alter_info->create_list);
562
949
  uint32_t total_uneven_bit_length= 0;
563
950
 
564
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
565
 
 
566
951
  select_field_pos= alter_info->create_list.elements - select_field_count;
567
952
  null_fields=blob_columns=0;
568
 
  max_key_length= engine->max_key_length();
 
953
  create_info->varchar= 0;
 
954
  max_key_length= file->max_key_length();
569
955
 
570
956
  for (field_no=0; (sql_field=it++) ; field_no++)
571
957
  {
610
996
        (sql_field->sql_type == DRIZZLE_TYPE_ENUM))
611
997
    {
612
998
      /*
613
 
        Starting from 5.1 we work here with a copy of CreateField
 
999
        Starting from 5.1 we work here with a copy of Create_field
614
1000
        created by the caller, not with the instance that was
615
1001
        originally created during parsing. It's OK to create
616
1002
        a temporary item and initialize with it a member of the
649
1035
        */
650
1036
        interval= sql_field->interval= typelib(session->mem_root,
651
1037
                                               sql_field->interval_list);
652
 
 
653
1038
        List_iterator<String> int_it(sql_field->interval_list);
654
1039
        String conv, *tmp;
655
1040
        char comma_buf[4];
657
1042
                                          (unsigned char*) comma_buf +
658
1043
                                          sizeof(comma_buf));
659
1044
        assert(comma_length > 0);
660
 
 
661
1045
        for (uint32_t i= 0; (tmp= int_it++); i++)
662
1046
        {
663
1047
          uint32_t lengthsp;
710
1094
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
711
1095
        sql_field->length= field_length;
712
1096
      }
713
 
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
 
1097
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
714
1098
    }
715
1099
 
716
1100
    sql_field->create_length_to_internal_length();
765
1149
            null_fields--;
766
1150
          sql_field->flags=             dup_field->flags;
767
1151
          sql_field->interval=          dup_field->interval;
 
1152
          sql_field->vcol_info=         dup_field->vcol_info;
 
1153
          sql_field->is_stored=      dup_field->is_stored;
768
1154
          it2.remove();                 // Remove first (create) definition
769
1155
          select_field_pos--;
770
1156
          break;
771
1157
        }
772
1158
      }
773
1159
    }
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)))
 
1160
    /* Don't pack rows in old tables if the user has requested this */
 
1161
    if ((sql_field->flags & BLOB_FLAG) ||
 
1162
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
779
1163
      (*db_options)|= HA_OPTION_PACK_RECORD;
780
1164
    it2.rewind();
781
1165
  }
790
1174
    assert(sql_field->charset != 0);
791
1175
 
792
1176
    if (prepare_create_field(sql_field, &blob_columns,
793
 
                             &timestamps, &timestamps_with_niladic))
 
1177
                             &timestamps, &timestamps_with_niladic,
 
1178
                             file->ha_table_flags()))
794
1179
      return(true);
 
1180
    if (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
 
1181
      create_info->varchar= true;
795
1182
    sql_field->offset= record_offset;
796
1183
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
797
1184
      auto_increment++;
 
1185
    /*
 
1186
          For now skip fields that are not physically stored in the database
 
1187
          (virtual fields) and update their offset later
 
1188
          (see the next loop).
 
1189
        */
 
1190
    if (sql_field->is_stored)
 
1191
      record_offset+= sql_field->pack_length;
 
1192
  }
 
1193
  /* Update virtual fields' offset */
 
1194
  it.rewind();
 
1195
  while ((sql_field=it++))
 
1196
  {
 
1197
    if (not sql_field->is_stored)
 
1198
    {
 
1199
      sql_field->offset= record_offset;
 
1200
      record_offset+= sql_field->pack_length;
 
1201
    }
798
1202
  }
799
1203
  if (timestamps_with_niladic > 1)
800
1204
  {
808
1212
    return(true);
809
1213
  }
810
1214
  if (auto_increment &&
811
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1215
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
812
1216
  {
813
1217
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
814
1218
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
815
1219
    return(true);
816
1220
  }
817
1221
 
818
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1222
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
819
1223
  {
820
1224
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
821
1225
               MYF(0));
856
1260
      continue;
857
1261
    }
858
1262
    (*key_count)++;
859
 
    tmp= engine->max_key_parts();
 
1263
    tmp=file->max_key_parts();
860
1264
    if (key->columns.elements > tmp)
861
1265
    {
862
1266
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
905
1309
      return(true);
906
1310
    }
907
1311
  }
908
 
  tmp= engine->max_keys();
 
1312
  tmp=file->max_keys();
909
1313
  if (*key_count > tmp)
910
1314
  {
911
1315
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
912
1316
    return(true);
913
1317
  }
914
1318
 
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);
 
1319
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1320
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
917
1321
  if (!*key_info_buffer || ! key_part_info)
918
1322
    return(true);                               // Out of memory
919
1323
 
960
1364
    */
961
1365
    key_info->block_size= (key->key_create_info.block_size ?
962
1366
                           key->key_create_info.block_size :
963
 
                           create_proto.options().key_block_size());
 
1367
                           create_info->key_block_size);
964
1368
 
965
1369
    if (key_info->block_size)
966
1370
      key_info->flags|= HA_USES_BLOCK_SIZE;
976
1380
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
977
1381
               key->key_create_info.comment.str,"INDEX COMMENT",
978
1382
               (uint32_t) INDEX_COMMENT_MAXLEN);
979
 
      return -1;
 
1383
      return(-1);
980
1384
    }
981
1385
 
982
1386
    key_info->comment.length= key->key_create_info.comment.length;
986
1390
      key_info->comment.str= key->key_create_info.comment.str;
987
1391
    }
988
1392
 
989
 
    message::Table::Field *protofield= NULL;
990
 
 
991
1393
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
992
1394
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
993
1395
    {
994
1396
      uint32_t length;
995
1397
      Key_part_spec *dup_column;
996
 
      int proto_field_nr= 0;
997
1398
 
998
1399
      it.rewind();
999
1400
      field=0;
1000
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
1401
      while ((sql_field=it++) &&
1001
1402
             my_strcasecmp(system_charset_info,
1002
1403
                           column->field_name.str,
1003
1404
                           sql_field->field_name))
1010
1411
      while ((dup_column= cols2++) != column)
1011
1412
      {
1012
1413
        if (!my_strcasecmp(system_charset_info,
1013
 
                           column->field_name.str, dup_column->field_name.str))
 
1414
                           column->field_name.str, dup_column->field_name.str))
1014
1415
        {
1015
1416
          my_printf_error(ER_DUP_FIELDNAME,
1016
1417
                          ER(ER_DUP_FIELDNAME),MYF(0),
1019
1420
        }
1020
1421
      }
1021
1422
      cols2.rewind();
1022
 
 
1023
 
      if (create_proto.field_size() > 0)
1024
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1025
 
 
1026
1423
      {
1027
 
        column->length*= sql_field->charset->mbmaxlen;
 
1424
        column->length*= sql_field->charset->mbmaxlen;
1028
1425
 
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;
 
1426
        if (f_is_blob(sql_field->pack_flag))
 
1427
        {
 
1428
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
1429
          {
 
1430
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
1431
            return(true);
 
1432
          }
 
1433
          if (!column->length)
 
1434
          {
 
1435
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
1436
            return(true);
 
1437
          }
 
1438
        }
 
1439
        if (not sql_field->is_stored)
 
1440
        {
 
1441
          /* Key fields must always be physically stored. */
 
1442
          my_error(ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN, MYF(0));
 
1443
          return(true);
 
1444
        }
 
1445
        if (key->type == Key::PRIMARY && sql_field->vcol_info)
 
1446
        {
 
1447
          my_error(ER_PRIMARY_KEY_BASED_ON_VIRTUAL_COLUMN, MYF(0));
 
1448
          return(true);
 
1449
        }
 
1450
        if (!(sql_field->flags & NOT_NULL_FLAG))
 
1451
        {
 
1452
          if (key->type == Key::PRIMARY)
 
1453
          {
 
1454
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
1455
            sql_field->flags|= NOT_NULL_FLAG;
 
1456
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1048
1457
            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
 
1458
          }
 
1459
          else
1059
1460
          {
1060
1461
            key_info->flags|= HA_NULL_PART_KEY;
1061
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1462
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1062
1463
            {
1063
1464
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1064
 
              return true;
 
1465
              return(true);
1065
1466
            }
1066
1467
          }
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
 
        }
 
1468
        }
 
1469
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
1470
        {
 
1471
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
 
1472
            auto_increment--;                   // Field is used
 
1473
        }
1073
1474
      }
1074
1475
 
1075
1476
      key_part_info->fieldnr= field;
1079
1480
 
1080
1481
      if (column->length)
1081
1482
      {
1082
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
1483
        if (f_is_blob(sql_field->pack_flag))
1083
1484
        {
1084
1485
          if ((length=column->length) > max_key_length ||
1085
 
              length > engine->max_key_part_length())
 
1486
              length > file->max_key_part_length())
1086
1487
          {
1087
 
            length= min(max_key_length, engine->max_key_part_length());
 
1488
            length=cmin(max_key_length, file->max_key_part_length());
1088
1489
            if (key->type == Key::MULTIPLE)
1089
1490
            {
1090
1491
              /* not a critical problem */
1104
1505
          }
1105
1506
        }
1106
1507
        else if ((column->length > length ||
1107
 
            ! Field::type_can_have_key_part(sql_field->sql_type)))
 
1508
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
 
1509
                   ((f_is_packed(sql_field->pack_flag) ||
 
1510
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
 
1511
                      (key_info->flags & HA_NOSAME))) &&
 
1512
                    column->length != length)))
1108
1513
        {
1109
1514
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1110
1515
          return(true);
1111
1516
        }
1112
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1113
 
        {
 
1517
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1114
1518
          length=column->length;
1115
 
        }
1116
1519
      }
1117
1520
      else if (length == 0)
1118
1521
      {
1119
1522
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1120
1523
          return(true);
1121
1524
      }
1122
 
      if (length > engine->max_key_part_length())
 
1525
      if (length > file->max_key_part_length())
1123
1526
      {
1124
 
        length= engine->max_key_part_length();
 
1527
        length= file->max_key_part_length();
1125
1528
        if (key->type == Key::MULTIPLE)
1126
1529
        {
1127
1530
          /* not a critical problem */
1144
1547
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1145
1548
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1146
1549
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1147
 
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1550
            sql_field->pack_flag & FIELDFLAG_BLOB)))
1148
1551
      {
1149
 
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
 
1552
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1150
1553
            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;
 
1554
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
1555
        else
 
1556
          key_info->flags|= HA_PACK_KEY;
1154
1557
      }
1155
1558
      /* Check if the key segment is partial, set the key flag accordingly */
1156
1559
      if (length != sql_field->key_length)
1201
1604
    key_info++;
1202
1605
  }
1203
1606
  if (!unique_key && !primary_key &&
1204
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1607
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1205
1608
  {
1206
1609
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1207
1610
    return(true);
1212
1615
    return(true);
1213
1616
  }
1214
1617
  /* Sort keys in optimized order */
1215
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1216
 
                     (qsort_cmp) sort_keys);
 
1618
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1619
           (qsort_cmp) sort_keys);
 
1620
  create_info->null_bits= null_fields;
1217
1621
 
1218
1622
  /* Check fields. */
1219
1623
  it.rewind();
1263
1667
*/
1264
1668
 
1265
1669
static bool prepare_blob_field(Session *,
1266
 
                               CreateField *sql_field)
 
1670
                               Create_field *sql_field)
1267
1671
{
1268
1672
 
1269
1673
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
1271
1675
  {
1272
1676
    my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1273
1677
             MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1274
 
    return 1;
 
1678
    return(1);
1275
1679
  }
1276
1680
 
1277
1681
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1279
1683
    if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1280
1684
    {
1281
1685
      /* The user has given a length to the blob column */
 
1686
      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1282
1687
      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1283
1688
    }
1284
1689
    sql_field->length= 0;
1285
1690
  }
1286
 
  return 0;
1287
 
}
1288
 
 
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;
 
1691
  return(0);
1386
1692
}
1387
1693
 
1388
1694
 
1389
1695
/*
1390
 
  Ignore the name of this function... it locks :(
1391
 
 
1392
1696
  Create a table
1393
1697
 
1394
1698
  SYNOPSIS
1411
1715
    that concurrent operations won't intervene. mysql_create_table()
1412
1716
    is a wrapper that can be used for this.
1413
1717
 
 
1718
    no_log is needed for the case of CREATE ... SELECT,
 
1719
    as the logging will be done later in sql_insert.cc
 
1720
    select_field_count is also used for CREATE ... SELECT,
 
1721
    and must be zero for standard create of table.
 
1722
 
1414
1723
  RETURN VALUES
1415
1724
    false OK
1416
1725
    true  error
1417
1726
*/
1418
1727
 
1419
1728
bool mysql_create_table_no_lock(Session *session,
1420
 
                                TableIdentifier &identifier,
 
1729
                                const char *db, const char *table_name,
1421
1730
                                HA_CREATE_INFO *create_info,
1422
 
                                message::Table &table_proto,
1423
 
                                AlterInfo *alter_info,
 
1731
                                Alter_info *alter_info,
1424
1732
                                bool internal_tmp_table,
1425
1733
                                uint32_t select_field_count,
1426
 
                                bool is_if_not_exists)
 
1734
                                bool lock_open_lock)
1427
1735
{
 
1736
  char          path[FN_REFLEN];
 
1737
  uint32_t          path_length;
 
1738
  const char    *alias;
1428
1739
  uint          db_options, key_count;
1429
1740
  KEY           *key_info_buffer;
 
1741
  handler       *file;
1430
1742
  bool          error= true;
1431
 
  TableShare share;
1432
 
 
1433
1743
  /* Check for duplicate fields and check type of table to create */
1434
 
  if (not alter_info->create_list.elements)
 
1744
  if (!alter_info->create_list.elements)
1435
1745
  {
1436
1746
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1437
1747
               MYF(0));
1438
 
    return true;
 
1748
    return(true);
1439
1749
  }
1440
 
  assert(identifier.getTableName() == table_proto.name());
 
1750
  if (check_engine(session, table_name, create_info))
 
1751
    return(true);
1441
1752
  db_options= create_info->table_options;
1442
 
 
1443
1753
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
1444
1754
    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,
 
1755
  alias= table_case_name(create_info, table_name);
 
1756
  if (!(file= get_new_handler((TABLE_SHARE*) 0, session->mem_root,
 
1757
                              create_info->db_type)))
 
1758
  {
 
1759
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
1760
    return(true);
 
1761
  }
 
1762
 
 
1763
  set_table_default_charset(session, create_info, (char*) db);
 
1764
 
 
1765
  if (mysql_prepare_create_table(session, create_info, alter_info,
1450
1766
                                 internal_tmp_table,
1451
 
                                 &db_options,
1452
 
                                 &key_info_buffer, &key_count,
1453
 
                                 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);
 
1767
                                 &db_options, file,
 
1768
                          &key_info_buffer, &key_count,
 
1769
                          select_field_count))
 
1770
    goto err;
 
1771
 
 
1772
      /* Check if table exists */
 
1773
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1774
  {
 
1775
    path_length= build_tmptable_filename(session, path, sizeof(path));
 
1776
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
1777
  }
 
1778
  else
 
1779
  {
 
1780
 #ifdef FN_DEVCHAR
 
1781
    /* check if the table name contains FN_DEVCHAR when defined */
 
1782
    if (strchr(alias, FN_DEVCHAR))
 
1783
    {
 
1784
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
 
1785
      return(true);
 
1786
    }
 
1787
#endif
 
1788
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
1789
                                      internal_tmp_table ? FN_IS_TMP : 0);
 
1790
  }
 
1791
 
 
1792
  /* Check if table already exists */
 
1793
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1794
      find_temporary_table(session, db, table_name))
 
1795
  {
 
1796
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1797
    {
 
1798
      create_info->table_existed= 1;            // Mark that table existed
 
1799
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1800
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1801
                          alias);
 
1802
      error= 0;
 
1803
      goto err;
 
1804
    }
 
1805
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
 
1806
    goto err;
 
1807
  }
 
1808
 
 
1809
  if (lock_open_lock)
 
1810
    pthread_mutex_lock(&LOCK_open);
 
1811
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1812
  {
 
1813
    if (!access(path,F_OK))
 
1814
    {
 
1815
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1816
        goto warn;
 
1817
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1818
      goto unlock_and_end;
 
1819
    }
 
1820
    /*
 
1821
      We don't assert here, but check the result, because the table could be
 
1822
      in the table definition cache and in the same time the .frm could be
 
1823
      missing from the disk, in case of manual intervention which deletes
 
1824
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1825
      Then she could create the table. This case is pretty obscure and
 
1826
      therefore we don't introduce a new error message only for it.
 
1827
    */
 
1828
    if (get_cached_table_share(db, alias))
 
1829
    {
 
1830
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1831
      goto unlock_and_end;
 
1832
    }
 
1833
  }
 
1834
 
 
1835
  /*
 
1836
    Check that table with given name does not already
 
1837
    exist in any storage engine. In such a case it should
 
1838
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1839
    unless user specified CREATE TABLE IF EXISTS
 
1840
    The LOCK_open mutex has been locked to make sure no
 
1841
    one else is attempting to discover the table. Since
 
1842
    it's not on disk as a frm file, no one could be using it!
 
1843
  */
 
1844
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1845
  {
 
1846
    bool create_if_not_exists =
 
1847
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1848
    int retcode = ha_table_exists_in_engine(session, db, table_name);
 
1849
    switch (retcode)
 
1850
    {
 
1851
      case HA_ERR_NO_SUCH_TABLE:
 
1852
        /* Normal case, no table exists. we can go and create it */
 
1853
        break;
 
1854
      case HA_ERR_TABLE_EXIST:
 
1855
 
 
1856
      if (create_if_not_exists)
 
1857
        goto warn;
 
1858
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1859
      goto unlock_and_end;
 
1860
        break;
 
1861
      default:
 
1862
        my_error(retcode, MYF(0),table_name);
 
1863
        goto unlock_and_end;
 
1864
    }
 
1865
  }
 
1866
 
 
1867
  session->set_proc_info("creating table");
 
1868
  create_info->table_existed= 0;                // Mark that table is created
 
1869
 
 
1870
#ifdef HAVE_READLINK
 
1871
  if (test_if_data_home_dir(create_info->data_file_name))
 
1872
  {
 
1873
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
 
1874
    goto unlock_and_end;
 
1875
  }
 
1876
  if (test_if_data_home_dir(create_info->index_file_name))
 
1877
  {
 
1878
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
 
1879
    goto unlock_and_end;
 
1880
  }
 
1881
 
 
1882
  if (!my_use_symdir)
 
1883
#endif /* HAVE_READLINK */
 
1884
  {
 
1885
    if (create_info->data_file_name)
 
1886
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1887
                   "DATA DIRECTORY option ignored");
 
1888
    if (create_info->index_file_name)
 
1889
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1890
                   "INDEX DIRECTORY option ignored");
 
1891
    create_info->data_file_name= create_info->index_file_name= 0;
 
1892
  }
 
1893
  create_info->table_options=db_options;
 
1894
 
 
1895
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
 
1896
  if (rea_create_table(session, path, db, table_name,
 
1897
                       create_info, alter_info->create_list,
 
1898
                       key_count, key_info_buffer, file, false))
 
1899
    goto unlock_and_end;
 
1900
 
 
1901
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1902
  {
 
1903
    /* Open table and put in temporary table list */
 
1904
    if (!(open_temporary_table(session, path, db, table_name, 1, OTM_OPEN)))
 
1905
    {
 
1906
      (void) rm_temporary_table(create_info->db_type, path);
 
1907
      goto unlock_and_end;
 
1908
    }
 
1909
    session->thread_specific_used= true;
 
1910
  }
 
1911
 
 
1912
  /*
 
1913
    Don't write statement if:
 
1914
    - It is an internal temporary table,
 
1915
    - Row-based logging is used and it we are creating a temporary table, or
 
1916
    - The binary log is not open.
 
1917
    Otherwise, the statement shall be binlogged.
 
1918
   */
 
1919
  if (!internal_tmp_table &&
 
1920
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1921
    write_bin_log(session, true, session->query, session->query_length);
 
1922
  error= false;
 
1923
unlock_and_end:
 
1924
  if (lock_open_lock)
1465
1925
    pthread_mutex_unlock(&LOCK_open);
1466
 
  }
1467
1926
 
 
1927
err:
1468
1928
  session->set_proc_info("After create");
1469
 
 
 
1929
  delete file;
1470
1930
  return(error);
 
1931
 
 
1932
warn:
 
1933
  error= false;
 
1934
  push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1935
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1936
                      alias);
 
1937
  create_info->table_existed= 1;                // Mark that table existed
 
1938
  goto unlock_and_end;
1471
1939
}
1472
1940
 
1473
 
/**
1474
 
  @note the following two methods implement create [temporary] table.
 
1941
 
 
1942
/*
 
1943
  Database locking aware wrapper for mysql_create_table_no_lock(),
1475
1944
*/
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)
 
1945
 
 
1946
bool mysql_create_table(Session *session, const char *db, const char *table_name,
 
1947
                        HA_CREATE_INFO *create_info,
 
1948
                        Alter_info *alter_info,
 
1949
                        bool internal_tmp_table,
 
1950
                        uint32_t select_field_count)
1484
1951
{
1485
 
  Table *name_lock= NULL;
 
1952
  Table *name_lock= 0;
1486
1953
  bool result;
1487
1954
 
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());
 
1955
  /* Wait for any database locks */
 
1956
  pthread_mutex_lock(&LOCK_lock_db);
 
1957
  while (!session->killed &&
 
1958
         hash_search(&lock_db_cache,(unsigned char*) db, strlen(db)))
 
1959
  {
 
1960
    wait_for_condition(session, &LOCK_lock_db, &COND_refresh);
 
1961
    pthread_mutex_lock(&LOCK_lock_db);
 
1962
  }
 
1963
 
 
1964
  if (session->killed)
 
1965
  {
 
1966
    pthread_mutex_unlock(&LOCK_lock_db);
 
1967
    return(true);
 
1968
  }
 
1969
  creating_table++;
 
1970
  pthread_mutex_unlock(&LOCK_lock_db);
 
1971
 
 
1972
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1973
  {
 
1974
    if (lock_table_name_if_not_cached(session, db, table_name, &name_lock))
 
1975
    {
1505
1976
      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
 
 
 
1977
      goto unlock;
 
1978
    }
 
1979
    if (!name_lock)
 
1980
    {
 
1981
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1982
      {
 
1983
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1984
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1985
                            table_name);
 
1986
        create_info->table_existed= 1;
 
1987
        result= false;
 
1988
      }
 
1989
      else
 
1990
      {
 
1991
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1992
        result= true;
 
1993
      }
 
1994
      goto unlock;
 
1995
    }
 
1996
  }
 
1997
 
 
1998
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1999
                                     alter_info,
 
2000
                                     internal_tmp_table,
 
2001
                                     select_field_count, true);
 
2002
 
 
2003
unlock:
1520
2004
  if (name_lock)
1521
2005
  {
1522
 
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1523
 
    session->unlink_open_table(name_lock);
 
2006
    pthread_mutex_lock(&LOCK_open);
 
2007
    unlink_open_table(session, name_lock, false);
1524
2008
    pthread_mutex_unlock(&LOCK_open);
1525
2009
  }
1526
 
 
 
2010
  pthread_mutex_lock(&LOCK_lock_db);
 
2011
  if (!--creating_table && creating_database)
 
2012
    pthread_cond_signal(&COND_refresh);
 
2013
  pthread_mutex_unlock(&LOCK_lock_db);
1527
2014
  return(result);
1528
2015
}
1529
2016
 
1530
2017
 
1531
2018
/*
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
2019
** Give the key name after the first field with an optional '_#' after
1568
2020
**/
1569
2021
 
1596
2048
  for (uint32_t i=2 ; i< 100; i++)
1597
2049
  {
1598
2050
    *buff_end= '_';
1599
 
    internal::int10_to_str(i, buff_end+1, 10);
 
2051
    int10_to_str(i, buff_end+1, 10);
1600
2052
    if (!check_if_keyname_exists(buff,start,end))
1601
 
      return memory::sql_strdup(buff);
 
2053
      return sql_strdup(buff);
1602
2054
  }
1603
2055
  return (char*) "not_specified";               // Should never happen
1604
2056
}
1608
2060
** Alter a table definition
1609
2061
****************************************************************************/
1610
2062
 
 
2063
 
1611
2064
/*
1612
2065
  Rename a table.
1613
2066
 
1614
2067
  SYNOPSIS
1615
2068
    mysql_rename_table()
1616
 
      base                      The plugin::StorageEngine handle.
 
2069
      base                      The handlerton handle.
1617
2070
      old_db                    The old database name.
1618
2071
      old_name                  The old table name.
1619
2072
      new_db                    The new database name.
1621
2074
      flags                     flags for build_table_filename().
1622
2075
                                FN_FROM_IS_TMP old_name is temporary.
1623
2076
                                FN_TO_IS_TMP   new_name is temporary.
 
2077
                                NO_FRM_RENAME  Don't rename the FRM file
 
2078
                                but only the table in the storage engine.
1624
2079
 
1625
2080
  RETURN
1626
2081
    false   OK
1628
2083
*/
1629
2084
 
1630
2085
bool
1631
 
mysql_rename_table(plugin::StorageEngine *base,
1632
 
                   TableIdentifier &from,
1633
 
                   TableIdentifier &to,
1634
 
                   uint32_t )
 
2086
mysql_rename_table(handlerton *base, const char *old_db,
 
2087
                   const char *old_name, const char *new_db,
 
2088
                   const char *new_name, uint32_t flags)
1635
2089
{
1636
2090
  Session *session= current_session;
1637
 
  int error= 0;
1638
 
 
1639
 
  assert(base);
1640
 
 
1641
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
1642
 
  {
1643
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1644
 
    return true;
1645
 
  }
1646
 
 
1647
 
  error= base->renameTable(*session, from, to);
1648
 
 
 
2091
  char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
 
2092
  char *from_base= from, *to_base= to;
 
2093
  char tmp_name[NAME_LEN+1];
 
2094
  handler *file;
 
2095
  int error=0;
 
2096
 
 
2097
  file= (base == NULL ? 0 :
 
2098
         get_new_handler((TABLE_SHARE*) 0, session->mem_root, base));
 
2099
 
 
2100
  build_table_filename(from, sizeof(from), old_db, old_name, "",
 
2101
                       flags & FN_FROM_IS_TMP);
 
2102
  build_table_filename(to, sizeof(to), new_db, new_name, "",
 
2103
                       flags & FN_TO_IS_TMP);
 
2104
 
 
2105
  /*
 
2106
    If lower_case_table_names == 2 (case-preserving but case-insensitive
 
2107
    file system) and the storage is not HA_FILE_BASED, we need to provide
 
2108
    a lowercase file name, but we leave the .frm in mixed case.
 
2109
   */
 
2110
  if (lower_case_table_names == 2 && file &&
 
2111
      !(file->ha_table_flags() & HA_FILE_BASED))
 
2112
  {
 
2113
    strcpy(tmp_name, old_name);
 
2114
    my_casedn_str(files_charset_info, tmp_name);
 
2115
    build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
 
2116
                         flags & FN_FROM_IS_TMP);
 
2117
    from_base= lc_from;
 
2118
 
 
2119
    strcpy(tmp_name, new_name);
 
2120
    my_casedn_str(files_charset_info, tmp_name);
 
2121
    build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
 
2122
                         flags & FN_TO_IS_TMP);
 
2123
    to_base= lc_to;
 
2124
  }
 
2125
  if (!file || !(error=file->ha_rename_table(from_base, to_base)))
 
2126
  {
 
2127
    if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
 
2128
    {
 
2129
      error=my_errno;
 
2130
      /* Restore old file name */
 
2131
      if (file)
 
2132
        file->ha_rename_table(to_base, from_base);
 
2133
    }
 
2134
 
 
2135
    if(!(flags & NO_FRM_RENAME)
 
2136
       && rename_table_proto_file(from_base, to_base))
 
2137
    {
 
2138
      error= errno;
 
2139
      rename_file_ext(to, from, reg_ext);
 
2140
      if (file)
 
2141
        file->ha_rename_table(to_base, from_base);
 
2142
    }
 
2143
  }
 
2144
  delete file;
1649
2145
  if (error == HA_ERR_WRONG_COMMAND)
1650
 
  {
1651
2146
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1652
 
  }
1653
2147
  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; 
 
2148
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
2149
  return(error != 0);
1662
2150
}
1663
2151
 
1664
2152
 
1667
2155
 
1668
2156
  SYNOPSIS
1669
2157
    wait_while_table_is_used()
1670
 
    session                     Thread Cursor
 
2158
    session                     Thread handler
1671
2159
    table               Table to remove from cache
1672
2160
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1673
2161
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1687
2175
 
1688
2176
  safe_mutex_assert_owner(&LOCK_open);
1689
2177
 
1690
 
  table->cursor->extra(function);
 
2178
  table->file->extra(function);
1691
2179
  /* Mark all tables that are in use as 'old' */
1692
 
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
 
2180
  mysql_lock_abort(session, table, true);       /* end threads waiting on lock */
1693
2181
 
1694
2182
  /* Wait until all there are no other threads that has this table open */
1695
 
  remove_table_from_cache(session, table->s->getSchemaName(),
 
2183
  remove_table_from_cache(session, table->s->db.str,
1696
2184
                          table->s->table_name.str,
1697
2185
                          RTFC_WAIT_OTHER_THREAD_FLAG);
 
2186
  return;
1698
2187
}
1699
2188
 
1700
2189
/*
1702
2191
 
1703
2192
  SYNOPSIS
1704
2193
    close_cached_table()
1705
 
    session                     Thread Cursor
 
2194
    session                     Thread handler
1706
2195
    table               Table to remove from cache
1707
2196
 
1708
2197
  NOTES
1714
2203
    Win32 clients must also have a WRITE LOCK on the table !
1715
2204
*/
1716
2205
 
1717
 
void Session::close_cached_table(Table *table)
 
2206
void close_cached_table(Session *session, Table *table)
1718
2207
{
1719
2208
 
1720
 
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
 
2209
  wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1721
2210
  /* Close lock if this is not got with LOCK TABLES */
1722
 
  if (lock)
 
2211
  if (session->lock)
1723
2212
  {
1724
 
    mysql_unlock_tables(this, lock);
1725
 
    lock= NULL;                 // Start locked threads
 
2213
    mysql_unlock_tables(session, session->lock);
 
2214
    session->lock=0;                    // Start locked threads
1726
2215
  }
1727
2216
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1728
 
  unlink_open_table(table);
 
2217
  unlink_open_table(session, table, true);
1729
2218
 
1730
2219
  /* When lock on LOCK_open is freed other threads can continue */
1731
2220
  broadcast_refresh();
1732
 
}
 
2221
  return;
 
2222
}
 
2223
 
 
2224
static int send_check_errmsg(Session *session, TableList* table,
 
2225
                             const char* operator_name, const char* errmsg)
 
2226
 
 
2227
{
 
2228
  Protocol *protocol= session->protocol;
 
2229
  protocol->prepare_for_resend();
 
2230
  protocol->store(table->alias, system_charset_info);
 
2231
  protocol->store((char*) operator_name, system_charset_info);
 
2232
  protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2233
  protocol->store(errmsg, system_charset_info);
 
2234
  session->clear_error();
 
2235
  if (protocol->write())
 
2236
    return -1;
 
2237
  return 1;
 
2238
}
 
2239
 
 
2240
 
 
2241
static int prepare_for_repair(Session *session, TableList *table_list,
 
2242
                              HA_CHECK_OPT *check_opt)
 
2243
{
 
2244
  int error= 0;
 
2245
  Table tmp_table, *table;
 
2246
  TABLE_SHARE *share;
 
2247
  char from[FN_REFLEN],tmp[FN_REFLEN+32];
 
2248
  const char **ext;
 
2249
  struct stat stat_info;
 
2250
 
 
2251
  if (!(check_opt->use_frm))
 
2252
    return(0);
 
2253
 
 
2254
  if (!(table= table_list->table))              /* if open_ltable failed */
 
2255
  {
 
2256
    char key[MAX_DBKEY_LENGTH];
 
2257
    uint32_t key_length;
 
2258
 
 
2259
    key_length= create_table_def_key(session, key, table_list, 0);
 
2260
    pthread_mutex_lock(&LOCK_open);
 
2261
    if (!(share= (get_table_share(session, table_list, key, key_length, 0,
 
2262
                                  &error))))
 
2263
    {
 
2264
      pthread_mutex_unlock(&LOCK_open);
 
2265
      return(0);                                // Can't open frm file
 
2266
    }
 
2267
 
 
2268
    if (open_table_from_share(session, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
 
2269
    {
 
2270
      release_table_share(share, RELEASE_NORMAL);
 
2271
      pthread_mutex_unlock(&LOCK_open);
 
2272
      return(0);                           // Out of memory
 
2273
    }
 
2274
    table= &tmp_table;
 
2275
    pthread_mutex_unlock(&LOCK_open);
 
2276
  }
 
2277
 
 
2278
  /*
 
2279
    REPAIR Table ... USE_FRM for temporary tables makes little sense.
 
2280
  */
 
2281
  if (table->s->tmp_table)
 
2282
  {
 
2283
    error= send_check_errmsg(session, table_list, "repair",
 
2284
                             "Cannot repair temporary table from .frm file");
 
2285
    goto end;
 
2286
  }
 
2287
 
 
2288
  /*
 
2289
    User gave us USE_FRM which means that the header in the index file is
 
2290
    trashed.
 
2291
    In this case we will try to fix the table the following way:
 
2292
    - Rename the data file to a temporary name
 
2293
    - Truncate the table
 
2294
    - Replace the new data file with the old one
 
2295
    - Run a normal repair using the new index file and the old data file
 
2296
  */
 
2297
 
 
2298
  /*
 
2299
    Check if this is a table type that stores index and data separately,
 
2300
    like ISAM or MyISAM. We assume fixed order of engine file name
 
2301
    extentions array. First element of engine file name extentions array
 
2302
    is meta/index file extention. Second element - data file extention.
 
2303
  */
 
2304
  ext= table->file->bas_ext();
 
2305
  if (!ext[0] || !ext[1])
 
2306
    goto end;                                   // No data file
 
2307
 
 
2308
  // Name of data file
 
2309
  sprintf(from,"%s%s", table->s->normalized_path.str, ext[1]);
 
2310
  if (stat(from, &stat_info))
 
2311
    goto end;                           // Can't use USE_FRM flag
 
2312
 
 
2313
  snprintf(tmp, sizeof(tmp), "%s-%lx_%"PRIx64,
 
2314
           from, (unsigned long)current_pid, session->thread_id);
 
2315
 
 
2316
  /* If we could open the table, close it */
 
2317
  if (table_list->table)
 
2318
  {
 
2319
    pthread_mutex_lock(&LOCK_open);
 
2320
    close_cached_table(session, table);
 
2321
    pthread_mutex_unlock(&LOCK_open);
 
2322
  }
 
2323
  if (lock_and_wait_for_table_name(session,table_list))
 
2324
  {
 
2325
    error= -1;
 
2326
    goto end;
 
2327
  }
 
2328
  if (my_rename(from, tmp, MYF(MY_WME)))
 
2329
  {
 
2330
    pthread_mutex_lock(&LOCK_open);
 
2331
    unlock_table_name(session, table_list);
 
2332
    pthread_mutex_unlock(&LOCK_open);
 
2333
    error= send_check_errmsg(session, table_list, "repair",
 
2334
                             "Failed renaming data file");
 
2335
    goto end;
 
2336
  }
 
2337
  if (mysql_truncate(session, table_list, 1))
 
2338
  {
 
2339
    pthread_mutex_lock(&LOCK_open);
 
2340
    unlock_table_name(session, table_list);
 
2341
    pthread_mutex_unlock(&LOCK_open);
 
2342
    error= send_check_errmsg(session, table_list, "repair",
 
2343
                             "Failed generating table from .frm file");
 
2344
    goto end;
 
2345
  }
 
2346
  if (my_rename(tmp, from, MYF(MY_WME)))
 
2347
  {
 
2348
    pthread_mutex_lock(&LOCK_open);
 
2349
    unlock_table_name(session, table_list);
 
2350
    pthread_mutex_unlock(&LOCK_open);
 
2351
    error= send_check_errmsg(session, table_list, "repair",
 
2352
                             "Failed restoring .MYD file");
 
2353
    goto end;
 
2354
  }
 
2355
 
 
2356
  /*
 
2357
    Now we should be able to open the partially repaired table
 
2358
    to finish the repair in the handler later on.
 
2359
  */
 
2360
  pthread_mutex_lock(&LOCK_open);
 
2361
  if (reopen_name_locked_table(session, table_list, true))
 
2362
  {
 
2363
    unlock_table_name(session, table_list);
 
2364
    pthread_mutex_unlock(&LOCK_open);
 
2365
    error= send_check_errmsg(session, table_list, "repair",
 
2366
                             "Failed to open partially repaired table");
 
2367
    goto end;
 
2368
  }
 
2369
  pthread_mutex_unlock(&LOCK_open);
 
2370
 
 
2371
end:
 
2372
  if (table == &tmp_table)
 
2373
  {
 
2374
    pthread_mutex_lock(&LOCK_open);
 
2375
    table->closefrm(true);                              // Free allocated memory
 
2376
    pthread_mutex_unlock(&LOCK_open);
 
2377
  }
 
2378
  return(error);
 
2379
}
 
2380
 
 
2381
 
1733
2382
 
1734
2383
/*
1735
2384
  RETURN VALUES
1742
2391
                              const char *operator_name,
1743
2392
                              thr_lock_type lock_type,
1744
2393
                              bool open_for_modify,
1745
 
                              int (Cursor::*operator_func)(Session *,
 
2394
                              bool no_warnings_for_error,
 
2395
                              uint32_t extra_open_options,
 
2396
                              int (*prepare_func)(Session *, TableList *,
 
2397
                                                  HA_CHECK_OPT *),
 
2398
                              int (handler::*operator_func)(Session *,
1746
2399
                                                            HA_CHECK_OPT *))
1747
2400
{
1748
2401
  TableList *table;
1749
2402
  Select_Lex *select= &session->lex->select_lex;
1750
2403
  List<Item> field_list;
1751
2404
  Item *item;
 
2405
  Protocol *protocol= session->protocol;
1752
2406
  LEX *lex= session->lex;
1753
2407
  int result_code= 0;
1754
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1755
2408
  const CHARSET_INFO * const cs= system_charset_info;
1756
2409
 
1757
 
  if (! session->endActiveTransaction())
1758
 
    return 1;
 
2410
  if (end_active_trans(session))
 
2411
    return(1);
1759
2412
  field_list.push_back(item = new Item_empty_string("Table",
1760
2413
                                                    NAME_CHAR_LEN * 2,
1761
2414
                                                    cs));
1766
2419
  item->maybe_null = 1;
1767
2420
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1768
2421
  item->maybe_null = 1;
1769
 
  if (session->client->sendFields(&field_list))
1770
 
    return true;
 
2422
  if (protocol->send_fields(&field_list,
 
2423
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
2424
    return(true);
 
2425
 
 
2426
  mysql_ha_rm_tables(session, tables, false);
1771
2427
 
1772
2428
  for (table= tables; table; table= table->next_local)
1773
2429
  {
1775
2431
    char* db = table->db;
1776
2432
    bool fatal_error=0;
1777
2433
 
1778
 
    snprintf(table_name, sizeof(table_name), "%s.%s",db,table->table_name);
 
2434
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2435
    session->open_options|= extra_open_options;
1779
2436
    table->lock_type= lock_type;
1780
2437
    /* open only one table from local list of command */
1781
2438
    {
1794
2451
      lex->query_tables= table;
1795
2452
      lex->query_tables_last= &table->next_global;
1796
2453
      lex->query_tables_own_last= 0;
1797
 
      session->no_warnings_for_error= 0;
 
2454
      session->no_warnings_for_error= no_warnings_for_error;
1798
2455
 
1799
 
      session->openTablesLock(table);
 
2456
      open_and_lock_tables(session, table);
1800
2457
      session->no_warnings_for_error= 0;
1801
2458
      table->next_global= save_next_global;
1802
2459
      table->next_local= save_next_local;
 
2460
      session->open_options&= ~extra_open_options;
 
2461
    }
 
2462
 
 
2463
    if (prepare_func)
 
2464
    {
 
2465
      switch ((*prepare_func)(session, table, check_opt)) {
 
2466
      case  1:           // error, message written to net
 
2467
        ha_autocommit_or_rollback(session, 1);
 
2468
        end_trans(session, ROLLBACK);
 
2469
        close_thread_tables(session);
 
2470
        continue;
 
2471
      case -1:           // error, message could be written to net
 
2472
        /* purecov: begin inspected */
 
2473
        goto err;
 
2474
        /* purecov: end */
 
2475
      default:           // should be 0 otherwise
 
2476
        ;
 
2477
      }
1803
2478
    }
1804
2479
 
1805
2480
    /*
1815
2490
      if (!session->warn_list.elements)
1816
2491
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1817
2492
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1818
 
      result_code= HA_ADMIN_CORRUPT;
1819
2493
      goto send_result;
1820
2494
    }
1821
2495
 
1822
2496
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
1823
2497
    {
 
2498
      /* purecov: begin inspected */
1824
2499
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1825
2500
      uint32_t length;
1826
 
      session->client->store(table_name);
1827
 
      session->client->store(operator_name);
1828
 
      session->client->store(STRING_WITH_LEN("error"));
 
2501
      protocol->prepare_for_resend();
 
2502
      protocol->store(table_name, system_charset_info);
 
2503
      protocol->store(operator_name, system_charset_info);
 
2504
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
1829
2505
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1830
2506
                       table_name);
1831
 
      session->client->store(buff, length);
1832
 
      transaction_services.ha_autocommit_or_rollback(session, false);
1833
 
      session->endTransaction(COMMIT);
1834
 
      session->close_thread_tables();
 
2507
      protocol->store(buff, length, system_charset_info);
 
2508
      ha_autocommit_or_rollback(session, 0);
 
2509
      end_trans(session, COMMIT);
 
2510
      close_thread_tables(session);
1835
2511
      lex->reset_query_tables_list(false);
1836
2512
      table->table=0;                           // For query cache
1837
 
      if (session->client->flush())
 
2513
      if (protocol->write())
1838
2514
        goto err;
1839
2515
      continue;
 
2516
      /* purecov: end */
1840
2517
    }
1841
2518
 
1842
2519
    /* Close all instances of the table to allow repair to rename files */
1843
2520
    if (lock_type == TL_WRITE && table->table->s->version)
1844
2521
    {
1845
 
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2522
      pthread_mutex_lock(&LOCK_open);
1846
2523
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1847
2524
                                              "Waiting to get writelock");
1848
 
      mysql_lock_abort(session,table->table);
1849
 
      remove_table_from_cache(session, table->table->s->getSchemaName(),
 
2525
      mysql_lock_abort(session,table->table, true);
 
2526
      remove_table_from_cache(session, table->table->s->db.str,
1850
2527
                              table->table->s->table_name.str,
1851
2528
                              RTFC_WAIT_OTHER_THREAD_FLAG |
1852
2529
                              RTFC_CHECK_KILLED_FLAG);
1856
2533
      open_for_modify= 0;
1857
2534
    }
1858
2535
 
1859
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
2536
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2537
    {
 
2538
      /* purecov: begin inspected */
 
2539
      protocol->prepare_for_resend();
 
2540
      protocol->store(table_name, system_charset_info);
 
2541
      protocol->store(operator_name, system_charset_info);
 
2542
      protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
 
2543
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
 
2544
                      system_charset_info);
 
2545
      if (protocol->write())
 
2546
        goto err;
 
2547
      /* purecov: end */
 
2548
    }
 
2549
 
 
2550
    if (operator_func == &handler::ha_repair && !(check_opt->use_frm))
 
2551
    {
 
2552
      if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
 
2553
          (table->table->file->ha_check_for_upgrade(check_opt) ==
 
2554
           HA_ADMIN_NEEDS_ALTER))
 
2555
      {
 
2556
        ha_autocommit_or_rollback(session, 1);
 
2557
        close_thread_tables(session);
 
2558
        result_code= mysql_recreate_table(session, table);
 
2559
        /*
 
2560
          mysql_recreate_table() can push OK or ERROR.
 
2561
          Clear 'OK' status. If there is an error, keep it:
 
2562
          we will store the error message in a result set row
 
2563
          and then clear.
 
2564
        */
 
2565
        if (session->main_da.is_ok())
 
2566
          session->main_da.reset_diagnostics_area();
 
2567
        goto send_result;
 
2568
      }
 
2569
    }
 
2570
 
 
2571
    result_code = (table->table->file->*operator_func)(session, check_opt);
1860
2572
 
1861
2573
send_result:
1862
2574
 
1867
2579
      DRIZZLE_ERROR *err;
1868
2580
      while ((err= it++))
1869
2581
      {
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())
 
2582
        protocol->prepare_for_resend();
 
2583
        protocol->store(table_name, system_charset_info);
 
2584
        protocol->store((char*) operator_name, system_charset_info);
 
2585
        protocol->store(warning_level_names[err->level].str,
 
2586
                        warning_level_names[err->level].length,
 
2587
                        system_charset_info);
 
2588
        protocol->store(err->msg, system_charset_info);
 
2589
        if (protocol->write())
1876
2590
          goto err;
1877
2591
      }
1878
2592
      drizzle_reset_errors(session, true);
1879
2593
    }
1880
 
    session->client->store(table_name);
1881
 
    session->client->store(operator_name);
 
2594
    protocol->prepare_for_resend();
 
2595
    protocol->store(table_name, system_charset_info);
 
2596
    protocol->store(operator_name, system_charset_info);
 
2597
 
 
2598
send_result_message:
1882
2599
 
1883
2600
    switch (result_code) {
1884
2601
    case HA_ADMIN_NOT_IMPLEMENTED:
1886
2603
        char buf[ERRMSGSIZE+20];
1887
2604
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1888
2605
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1889
 
        session->client->store(STRING_WITH_LEN("note"));
1890
 
        session->client->store(buf, length);
 
2606
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
2607
        protocol->store(buf, length, system_charset_info);
1891
2608
      }
1892
2609
      break;
1893
2610
 
1894
2611
    case HA_ADMIN_OK:
1895
 
      session->client->store(STRING_WITH_LEN("status"));
1896
 
      session->client->store(STRING_WITH_LEN("OK"));
 
2612
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2613
      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
1897
2614
      break;
1898
2615
 
1899
2616
    case HA_ADMIN_FAILED:
1900
 
      session->client->store(STRING_WITH_LEN("status"));
1901
 
      session->client->store(STRING_WITH_LEN("Operation failed"));
 
2617
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2618
      protocol->store(STRING_WITH_LEN("Operation failed"),
 
2619
                      system_charset_info);
1902
2620
      break;
1903
2621
 
1904
2622
    case HA_ADMIN_REJECT:
1905
 
      session->client->store(STRING_WITH_LEN("status"));
1906
 
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
 
2623
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2624
      protocol->store(STRING_WITH_LEN("Operation need committed state"),
 
2625
                      system_charset_info);
1907
2626
      open_for_modify= false;
1908
2627
      break;
1909
2628
 
1910
2629
    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"));
 
2630
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2631
      protocol->store(STRING_WITH_LEN("Table is already up to date"),
 
2632
                      system_charset_info);
1913
2633
      break;
1914
2634
 
1915
2635
    case HA_ADMIN_CORRUPT:
1916
 
      session->client->store(STRING_WITH_LEN("error"));
1917
 
      session->client->store(STRING_WITH_LEN("Corrupt"));
 
2636
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2637
      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
1918
2638
      fatal_error=1;
1919
2639
      break;
1920
2640
 
1921
2641
    case HA_ADMIN_INVALID:
1922
 
      session->client->store(STRING_WITH_LEN("error"));
1923
 
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1924
 
      break;
 
2642
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2643
      protocol->store(STRING_WITH_LEN("Invalid argument"),
 
2644
                      system_charset_info);
 
2645
      break;
 
2646
 
 
2647
    case HA_ADMIN_TRY_ALTER:
 
2648
    {
 
2649
      /*
 
2650
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2651
        "try with alter", so here we close the table, do an ALTER Table,
 
2652
        reopen the table and do ha_innobase::analyze() on it.
 
2653
      */
 
2654
      ha_autocommit_or_rollback(session, 0);
 
2655
      close_thread_tables(session);
 
2656
      TableList *save_next_local= table->next_local,
 
2657
                 *save_next_global= table->next_global;
 
2658
      table->next_local= table->next_global= 0;
 
2659
      result_code= mysql_recreate_table(session, table);
 
2660
      /*
 
2661
        mysql_recreate_table() can push OK or ERROR.
 
2662
        Clear 'OK' status. If there is an error, keep it:
 
2663
        we will store the error message in a result set row
 
2664
        and then clear.
 
2665
      */
 
2666
      if (session->main_da.is_ok())
 
2667
        session->main_da.reset_diagnostics_area();
 
2668
      ha_autocommit_or_rollback(session, 0);
 
2669
      close_thread_tables(session);
 
2670
      if (!result_code) // recreation went ok
 
2671
      {
 
2672
        if ((table->table= open_ltable(session, table, lock_type, 0)) &&
 
2673
            ((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
 
2674
          result_code= 0; // analyze went ok
 
2675
      }
 
2676
      if (result_code) // either mysql_recreate_table or analyze failed
 
2677
      {
 
2678
        assert(session->is_error());
 
2679
        if (session->is_error())
 
2680
        {
 
2681
          const char *err_msg= session->main_da.message();
 
2682
          if (!session->drizzleclient_vio_ok())
 
2683
          {
 
2684
            errmsg_printf(ERRMSG_LVL_ERROR, "%s", err_msg);
 
2685
          }
 
2686
          else
 
2687
          {
 
2688
            /* Hijack the row already in-progress. */
 
2689
            protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2690
            protocol->store(err_msg, system_charset_info);
 
2691
            (void)protocol->write();
 
2692
            /* Start off another row for HA_ADMIN_FAILED */
 
2693
            protocol->prepare_for_resend();
 
2694
            protocol->store(table_name, system_charset_info);
 
2695
            protocol->store(operator_name, system_charset_info);
 
2696
          }
 
2697
          session->clear_error();
 
2698
        }
 
2699
      }
 
2700
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2701
      table->next_local= save_next_local;
 
2702
      table->next_global= save_next_global;
 
2703
      goto send_result_message;
 
2704
    }
 
2705
    case HA_ADMIN_NEEDS_UPGRADE:
 
2706
    case HA_ADMIN_NEEDS_ALTER:
 
2707
    {
 
2708
      char buf[ERRMSGSIZE];
 
2709
      uint32_t length;
 
2710
 
 
2711
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2712
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2713
      protocol->store(buf, length, system_charset_info);
 
2714
      fatal_error=1;
 
2715
      break;
 
2716
    }
1925
2717
 
1926
2718
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1927
2719
      {
1929
2721
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1930
2722
                             _("Unknown - internal error %d during operation"),
1931
2723
                             result_code);
1932
 
        session->client->store(STRING_WITH_LEN("error"));
1933
 
        session->client->store(buf, length);
 
2724
        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2725
        protocol->store(buf, length, system_charset_info);
1934
2726
        fatal_error=1;
1935
2727
        break;
1936
2728
      }
1942
2734
      else if (open_for_modify)
1943
2735
      {
1944
2736
        if (table->table->s->tmp_table)
1945
 
          table->table->cursor->info(HA_STATUS_CONST);
 
2737
          table->table->file->info(HA_STATUS_CONST);
1946
2738
        else
1947
2739
        {
1948
2740
          pthread_mutex_lock(&LOCK_open);
1949
 
          remove_table_from_cache(session, table->table->s->getSchemaName(),
 
2741
          remove_table_from_cache(session, table->table->s->db.str,
1950
2742
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
1951
2743
          pthread_mutex_unlock(&LOCK_open);
1952
2744
        }
1953
2745
      }
1954
2746
    }
1955
 
    transaction_services.ha_autocommit_or_rollback(session, false);
1956
 
    session->endTransaction(COMMIT);
1957
 
    session->close_thread_tables();
 
2747
    ha_autocommit_or_rollback(session, 0);
 
2748
    end_trans(session, COMMIT);
 
2749
    close_thread_tables(session);
1958
2750
    table->table=0;                             // For query cache
1959
 
    if (session->client->flush())
 
2751
    if (protocol->write())
1960
2752
      goto err;
1961
2753
  }
1962
2754
 
1964
2756
  return(false);
1965
2757
 
1966
2758
err:
1967
 
  transaction_services.ha_autocommit_or_rollback(session, true);
1968
 
  session->endTransaction(ROLLBACK);
1969
 
  session->close_thread_tables();                       // Shouldn't be needed
 
2759
  ha_autocommit_or_rollback(session, 1);
 
2760
  end_trans(session, ROLLBACK);
 
2761
  close_thread_tables(session);                 // Shouldn't be needed
1970
2762
  if (table)
1971
2763
    table->table=0;
1972
2764
  return(true);
1973
2765
}
1974
2766
 
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)
1994
 
{
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;
2028
 
}
2029
 
 
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)
2049
 
{
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
 
  }
2063
 
  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;
 
2767
 
 
2768
bool mysql_repair_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2769
{
 
2770
  return(mysql_admin_table(session, tables, check_opt,
 
2771
                           "repair", TL_WRITE, 1,
 
2772
                           check_opt->use_frm,
 
2773
                           HA_OPEN_FOR_REPAIR,
 
2774
                           &prepare_for_repair,
 
2775
                           &handler::ha_repair));
 
2776
}
 
2777
 
 
2778
 
 
2779
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2780
{
 
2781
  return(mysql_admin_table(session, tables, check_opt,
 
2782
                           "optimize", TL_WRITE, 1,0,0,0,
 
2783
                           &handler::ha_optimize));
 
2784
}
 
2785
 
 
2786
 
 
2787
/*
 
2788
  Assigned specified indexes for a table into key cache
 
2789
 
 
2790
  SYNOPSIS
 
2791
    mysql_assign_to_keycache()
 
2792
    session             Thread object
 
2793
    tables      Table list (one table only)
 
2794
 
 
2795
  RETURN VALUES
 
2796
   false ok
 
2797
   true  error
 
2798
*/
 
2799
 
 
2800
bool mysql_assign_to_keycache(Session* session, TableList* tables,
 
2801
                             LEX_STRING *key_cache_name)
 
2802
{
 
2803
  HA_CHECK_OPT check_opt;
 
2804
  KEY_CACHE *key_cache;
 
2805
 
 
2806
  check_opt.init();
 
2807
  pthread_mutex_lock(&LOCK_global_system_variables);
 
2808
  if (!(key_cache= get_key_cache(key_cache_name)))
 
2809
  {
 
2810
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2811
    my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
 
2812
    return(true);
 
2813
  }
 
2814
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
2815
  check_opt.key_cache= key_cache;
 
2816
  return(mysql_admin_table(session, tables, &check_opt,
 
2817
                                "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
 
2818
                                0, 0, &handler::assign_to_keycache));
 
2819
}
 
2820
 
 
2821
 
 
2822
/*
 
2823
  Reassign all tables assigned to a key cache to another key cache
 
2824
 
 
2825
  SYNOPSIS
 
2826
    reassign_keycache_tables()
 
2827
    session             Thread object
 
2828
    src_cache   Reference to the key cache to clean up
 
2829
    dest_cache  New key cache
 
2830
 
 
2831
  NOTES
 
2832
    This is called when one sets a key cache size to zero, in which
 
2833
    case we have to move the tables associated to this key cache to
 
2834
    the "default" one.
 
2835
 
 
2836
    One has to ensure that one never calls this function while
 
2837
    some other thread is changing the key cache. This is assured by
 
2838
    the caller setting src_cache->in_init before calling this function.
 
2839
 
 
2840
    We don't delete the old key cache as there may still be pointers pointing
 
2841
    to it for a while after this function returns.
 
2842
 
 
2843
 RETURN VALUES
 
2844
    0     ok
 
2845
*/
 
2846
 
 
2847
int reassign_keycache_tables(Session *,
 
2848
                             KEY_CACHE *src_cache,
 
2849
                             KEY_CACHE *dst_cache)
 
2850
{
 
2851
  assert(src_cache != dst_cache);
 
2852
  assert(src_cache->in_init);
 
2853
  src_cache->param_buff_size= 0;                // Free key cache
 
2854
  ha_resize_key_cache(src_cache);
 
2855
  ha_change_key_cache(src_cache, dst_cache);
 
2856
  return(0);
 
2857
}
 
2858
 
 
2859
/**
 
2860
  @brief          Create frm file based on I_S table
 
2861
 
 
2862
  @param[in]      session                      thread handler
 
2863
  @param[in]      schema_table             I_S table
 
2864
  @param[in]      dst_path                 path where frm should be created
 
2865
  @param[in]      create_info              Create info
 
2866
 
 
2867
  @return         Operation status
 
2868
    @retval       0                        success
 
2869
    @retval       1                        error
 
2870
*/
 
2871
bool mysql_create_like_schema_frm(Session* session, TableList* schema_table,
 
2872
                                  char *dst_path, HA_CREATE_INFO *create_info)
 
2873
{
 
2874
  HA_CREATE_INFO local_create_info;
 
2875
  Alter_info alter_info;
 
2876
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
2877
  uint32_t keys= schema_table->table->s->keys;
 
2878
  uint32_t db_options= 0;
 
2879
 
 
2880
  memset(&local_create_info, 0, sizeof(local_create_info));
 
2881
  local_create_info.db_type= schema_table->table->s->db_type();
 
2882
  local_create_info.row_type= schema_table->table->s->row_type;
 
2883
  local_create_info.default_table_charset=default_charset_info;
 
2884
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
2885
  schema_table->table->use_all_columns();
 
2886
  if (mysql_prepare_alter_table(session, schema_table->table,
 
2887
                                &local_create_info, &alter_info))
 
2888
    return true;
 
2889
 
 
2890
  if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
 
2891
                                 tmp_table, &db_options,
 
2892
                                 schema_table->table->file,
 
2893
                                 &schema_table->table->s->key_info, &keys, 0))
 
2894
    return true;
 
2895
 
 
2896
  local_create_info.max_rows= 0;
 
2897
  if (rea_create_table(session, dst_path, "system_tmp", "system_stupid_i_s_fix_nonsense",
 
2898
                       &local_create_info, alter_info.create_list,
 
2899
                       keys, schema_table->table->s->key_info,
 
2900
                       schema_table->table->file, true))
 
2901
    return true;
 
2902
 
 
2903
  return false;
2102
2904
}
2103
2905
 
2104
2906
/*
2116
2918
    true  error
2117
2919
*/
2118
2920
 
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)
 
2921
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2922
                             HA_CREATE_INFO *create_info)
2125
2923
{
2126
2924
  Table *name_lock= 0;
 
2925
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2926
  uint32_t dst_path_length;
2127
2927
  char *db= table->db;
2128
2928
  char *table_name= table->table_name;
 
2929
  int  err;
2129
2930
  bool res= true;
2130
2931
  uint32_t not_used;
2131
 
  bool was_created;
2132
2932
 
2133
2933
  /*
2134
2934
    By opening source table we guarantee that it exists and no concurrent
2135
2935
    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.
 
2936
    name-lock on target table name, which makes copying of .frm file,
 
2937
    call to ha_create_table() and binlogging atomic against concurrent DML
 
2938
    and DDL operations on target table. Thus by holding both these "locks"
 
2939
    we ensure that our statement is properly isolated from all concurrent
 
2940
    operations which matter.
2141
2941
  */
2142
 
  if (session->open_tables_from_list(&src_table, &not_used))
2143
 
    return true;
2144
 
 
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
 
 
 
2942
  if (open_tables(session, &src_table, &not_used, 0))
 
2943
    return(true);
 
2944
 
 
2945
  sprintf(src_path,"%s%s",src_table->table->s->path.str, reg_ext);
2149
2946
 
2150
2947
  /*
2151
2948
    Check that destination tables does not exist. Note that its name
2152
2949
    was already checked when it was added to the table list.
2153
2950
  */
2154
 
  bool table_exists= false;
2155
 
  if (destination_identifier.isTmp())
2156
 
  {
2157
 
    if (session->find_temporary_table(db, table_name))
2158
 
    {
2159
 
      table_exists= true;
2160
 
    }
2161
 
  }
2162
 
  else
2163
 
  {
2164
 
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2165
 
    {
2166
 
      if (name_lock)
 
2951
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2952
  {
 
2953
    if (find_temporary_table(session, db, table_name))
 
2954
      goto table_exists;
 
2955
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
 
2956
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
 
2957
  }
 
2958
  else
 
2959
  {
 
2960
    if (lock_table_name_if_not_cached(session, db, table_name, &name_lock))
 
2961
      goto err;
 
2962
    if (!name_lock)
 
2963
      goto table_exists;
 
2964
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2965
                                          db, table_name, reg_ext, 0);
 
2966
    if (!access(dst_path, F_OK))
 
2967
      goto table_exists;
 
2968
  }
 
2969
 
 
2970
  /*
 
2971
    Create a new table by copying from source table
 
2972
 
 
2973
    Altough exclusive name-lock on target table protects us from concurrent
 
2974
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2975
    to ha_create_table() in critical section protected by LOCK_open in order
 
2976
    to provide minimal atomicity against operations which disregard name-locks,
 
2977
    like I_S implementation, for example. This is a temporary and should not
 
2978
    be copied. Instead we should fix our code to always honor name-locks.
 
2979
 
 
2980
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2981
    during the call to ha_create_table(). See bug #28614 for more info.
 
2982
  */
 
2983
  pthread_mutex_lock(&LOCK_open);
 
2984
  if (src_table->schema_table)
 
2985
  {
 
2986
    if (mysql_create_like_schema_frm(session, src_table, dst_path, create_info))
 
2987
    {
 
2988
      pthread_mutex_unlock(&LOCK_open);
 
2989
      goto err;
 
2990
    }
 
2991
  }
 
2992
  else
 
2993
  {
 
2994
    int frmcopyr= my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE));
 
2995
 
 
2996
    string dfesrc(src_path);
 
2997
    string dfedst(dst_path);
 
2998
 
 
2999
    dfesrc.replace(dfesrc.find(".frm"), 4, ".dfe" );
 
3000
    dfedst.replace(dfedst.find(".frm"), 4, ".dfe" );
 
3001
 
 
3002
    int dfecopyr= my_copy(dfesrc.c_str(), dfedst.c_str(),
 
3003
                          MYF(MY_DONT_OVERWRITE_FILE));
 
3004
 
 
3005
    if(frmcopyr || dfecopyr) // FIXME: should handle only one fail.
 
3006
    {
 
3007
      if (my_errno == ENOENT)
 
3008
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
3009
      else
 
3010
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
3011
      pthread_mutex_unlock(&LOCK_open);
 
3012
      goto err;
 
3013
    }
 
3014
  }
 
3015
 
 
3016
  /*
 
3017
    As mysql_truncate don't work on a new table at this stage of
 
3018
    creation, instead create the table directly (for both normal
 
3019
    and temporary tables).
 
3020
  */
 
3021
  dst_path[dst_path_length - reg_ext_length]= '\0';  // Remove .frm
 
3022
  if (session->variables.keep_files_on_create)
 
3023
    create_info->options|= HA_CREATE_KEEP_FILES;
 
3024
  err= ha_create_table(session, dst_path, db, table_name, create_info, 1);
 
3025
  pthread_mutex_unlock(&LOCK_open);
 
3026
 
 
3027
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
3028
  {
 
3029
    if (err || !open_temporary_table(session, dst_path, db, table_name, 1,
 
3030
                                     OTM_OPEN))
 
3031
    {
 
3032
      (void) rm_temporary_table(create_info->db_type,
 
3033
                                dst_path);
 
3034
      goto err;     /* purecov: inspected */
 
3035
    }
 
3036
  }
 
3037
  else if (err)
 
3038
  {
 
3039
    (void) quick_rm_table(create_info->db_type, db,
 
3040
                          table_name, 0); /* purecov: inspected */
 
3041
    goto err;       /* purecov: inspected */
 
3042
  }
 
3043
 
 
3044
  /*
 
3045
    We have to write the query before we unlock the tables.
 
3046
  */
 
3047
  {
 
3048
    /*
 
3049
       Since temporary tables are not replicated under row-based
 
3050
       replication, CREATE TABLE ... LIKE ... needs special
 
3051
       treatement.  We have four cases to consider, according to the
 
3052
       following decision table:
 
3053
 
 
3054
           ==== ========= ========= ==============================
 
3055
           Case    Target    Source Write to binary log
 
3056
           ==== ========= ========= ==============================
 
3057
           1       normal    normal Original statement
 
3058
           2       normal temporary Generated statement
 
3059
           3    temporary    normal Nothing
 
3060
           4    temporary temporary Nothing
 
3061
           ==== ========= ========= ==============================
 
3062
    */
 
3063
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
3064
    {
 
3065
      if (src_table->table->s->tmp_table)               // Case 2
2167
3066
      {
2168
 
        pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2169
 
        session->unlink_open_table(name_lock);
 
3067
        char buf[2048];
 
3068
        String query(buf, sizeof(buf), system_charset_info);
 
3069
        query.length(0);  // Have to zero it since constructor doesn't
 
3070
 
 
3071
 
 
3072
        /*
 
3073
          Here we open the destination table, on which we already have
 
3074
          name-lock. This is needed for store_create_info() to work.
 
3075
          The table will be closed by unlink_open_table() at the end
 
3076
          of this function.
 
3077
        */
 
3078
        table->table= name_lock;
 
3079
        pthread_mutex_lock(&LOCK_open);
 
3080
        if (reopen_name_locked_table(session, table, false))
 
3081
        {
 
3082
          pthread_mutex_unlock(&LOCK_open);
 
3083
          goto err;
 
3084
        }
2170
3085
        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
 
 
 
3086
 
 
3087
        int result= store_create_info(session, table, &query,
 
3088
                                               create_info);
 
3089
 
 
3090
        assert(result == 0); // store_create_info() always return 0
 
3091
        write_bin_log(session, true, query.ptr(), query.length());
 
3092
      }
 
3093
      else                                      // Case 1
 
3094
        write_bin_log(session, true, session->query, session->query_length);
 
3095
    }
 
3096
    /*
 
3097
      Case 3 and 4 does nothing under RBR
 
3098
    */
 
3099
  }
 
3100
 
 
3101
  res= false;
 
3102
  goto err;
 
3103
 
 
3104
table_exists:
 
3105
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
3106
  {
 
3107
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
3108
    snprintf(warn_buff, sizeof(warn_buff),
 
3109
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
3110
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3111
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
3112
    res= false;
 
3113
  }
 
3114
  else
 
3115
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
3116
 
 
3117
err:
2239
3118
  if (name_lock)
2240
3119
  {
2241
 
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2242
 
    session->unlink_open_table(name_lock);
 
3120
    pthread_mutex_lock(&LOCK_open);
 
3121
    unlink_open_table(session, name_lock, false);
2243
3122
    pthread_mutex_unlock(&LOCK_open);
2244
3123
  }
2245
 
 
2246
3124
  return(res);
2247
3125
}
2248
3126
 
2252
3130
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2253
3131
 
2254
3132
  return(mysql_admin_table(session, tables, check_opt,
2255
 
                                "analyze", lock_type, true,
2256
 
                                &Cursor::ha_analyze));
 
3133
                                "analyze", lock_type, 1, 0, 0, 0,
 
3134
                                &handler::ha_analyze));
2257
3135
}
2258
3136
 
2259
3137
 
2263
3141
 
2264
3142
  return(mysql_admin_table(session, tables, check_opt,
2265
3143
                                "check", lock_type,
2266
 
                                false,
2267
 
                                &Cursor::ha_check));
 
3144
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
3145
                                &handler::ha_check));
 
3146
}
 
3147
 
 
3148
 
 
3149
/* table_list should contain just one table */
 
3150
static int
 
3151
mysql_discard_or_import_tablespace(Session *session,
 
3152
                                   TableList *table_list,
 
3153
                                   enum tablespace_op_type tablespace_op)
 
3154
{
 
3155
  Table *table;
 
3156
  bool discard;
 
3157
  int error;
 
3158
 
 
3159
  /*
 
3160
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
 
3161
    ALTER Table
 
3162
  */
 
3163
 
 
3164
  session->set_proc_info("discard_or_import_tablespace");
 
3165
 
 
3166
  discard= test(tablespace_op == DISCARD_TABLESPACE);
 
3167
 
 
3168
 /*
 
3169
   We set this flag so that ha_innobase::open and ::external_lock() do
 
3170
   not complain when we lock the table
 
3171
 */
 
3172
  session->tablespace_op= true;
 
3173
  if (!(table=open_ltable(session, table_list, TL_WRITE, 0)))
 
3174
  {
 
3175
    session->tablespace_op=false;
 
3176
    return(-1);
 
3177
  }
 
3178
 
 
3179
  error= table->file->ha_discard_or_import_tablespace(discard);
 
3180
 
 
3181
  session->set_proc_info("end");
 
3182
 
 
3183
  if (error)
 
3184
    goto err;
 
3185
 
 
3186
  /* The ALTER Table is always in its own transaction */
 
3187
  error = ha_autocommit_or_rollback(session, 0);
 
3188
  if (end_active_trans(session))
 
3189
    error=1;
 
3190
  if (error)
 
3191
    goto err;
 
3192
  write_bin_log(session, false, session->query, session->query_length);
 
3193
 
 
3194
err:
 
3195
  ha_autocommit_or_rollback(session, error);
 
3196
  session->tablespace_op=false;
 
3197
 
 
3198
  if (error == 0)
 
3199
  {
 
3200
    session->my_ok();
 
3201
    return(0);
 
3202
  }
 
3203
 
 
3204
  table->file->print_error(error, MYF(0));
 
3205
 
 
3206
  return(-1);
 
3207
}
 
3208
 
 
3209
/**
 
3210
  Copy all changes detected by parser to the HA_ALTER_FLAGS
 
3211
*/
 
3212
 
 
3213
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
 
3214
{
 
3215
  uint32_t flags= alter_info->flags;
 
3216
 
 
3217
  if (ALTER_ADD_COLUMN & flags)
 
3218
    *alter_flags|= HA_ADD_COLUMN;
 
3219
  if (ALTER_DROP_COLUMN & flags)
 
3220
    *alter_flags|= HA_DROP_COLUMN;
 
3221
  if (ALTER_RENAME & flags)
 
3222
    *alter_flags|= HA_RENAME_TABLE;
 
3223
  if (ALTER_CHANGE_COLUMN & flags)
 
3224
    *alter_flags|= HA_CHANGE_COLUMN;
 
3225
  if (ALTER_COLUMN_DEFAULT & flags)
 
3226
    *alter_flags|= HA_COLUMN_DEFAULT_VALUE;
 
3227
  if (ALTER_COLUMN_STORAGE & flags)
 
3228
    *alter_flags|= HA_COLUMN_STORAGE;
 
3229
  if (ALTER_COLUMN_FORMAT & flags)
 
3230
    *alter_flags|= HA_COLUMN_FORMAT;
 
3231
  if (ALTER_COLUMN_ORDER & flags)
 
3232
    *alter_flags|= HA_ALTER_COLUMN_ORDER;
 
3233
  if (ALTER_STORAGE & flags)
 
3234
    *alter_flags|= HA_ALTER_STORAGE;
 
3235
  if (ALTER_ROW_FORMAT & flags)
 
3236
    *alter_flags|= HA_ALTER_ROW_FORMAT;
 
3237
  if (ALTER_RECREATE & flags)
 
3238
    *alter_flags|= HA_RECREATE;
 
3239
  if (ALTER_FOREIGN_KEY & flags)
 
3240
    *alter_flags|= HA_ALTER_FOREIGN_KEY;
 
3241
}
 
3242
 
 
3243
 
 
3244
/**
 
3245
   @param       session                Thread
 
3246
   @param       table              The original table.
 
3247
   @param       alter_info         Alter options, fields and keys for the new
 
3248
                                   table.
 
3249
   @param       create_info        Create options for the new table.
 
3250
   @param       order_num          Number of order list elements.
 
3251
   @param[out]  ha_alter_flags  Flags that indicate what will be changed
 
3252
   @param[out]  ha_alter_info      Data structures needed for on-line alter
 
3253
   @param[out]  table_changes      Information about particular change
 
3254
 
 
3255
   First argument 'table' contains information of the original
 
3256
   table, which includes all corresponding parts that the new
 
3257
   table has in arguments create_list, key_list and create_info.
 
3258
 
 
3259
   By comparing the changes between the original and new table
 
3260
   we can determine how much it has changed after ALTER Table
 
3261
   and whether we need to make a copy of the table, or just change
 
3262
   the .frm file.
 
3263
 
 
3264
   Mark any changes detected in the ha_alter_flags.
 
3265
 
 
3266
   If there are no data changes, but index changes, 'index_drop_buffer'
 
3267
   and/or 'index_add_buffer' are populated with offsets into
 
3268
   table->key_info or key_info_buffer respectively for the indexes
 
3269
   that need to be dropped and/or (re-)created.
 
3270
 
 
3271
   @retval true  error
 
3272
   @retval false success
 
3273
*/
 
3274
 
 
3275
static
 
3276
bool
 
3277
compare_tables(Session *session,
 
3278
               Table *table,
 
3279
               Alter_info *alter_info,
 
3280
               HA_CREATE_INFO *create_info,
 
3281
               uint32_t order_num,
 
3282
               HA_ALTER_FLAGS *alter_flags,
 
3283
               HA_ALTER_INFO *ha_alter_info,
 
3284
               uint32_t *table_changes)
 
3285
{
 
3286
  Field **f_ptr, *field;
 
3287
  uint32_t table_changes_local= 0;
 
3288
  List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
 
3289
  Create_field *new_field;
 
3290
  KEY_PART_INFO *key_part;
 
3291
  KEY_PART_INFO *end;
 
3292
 
 
3293
  {
 
3294
    /*
 
3295
      Create a copy of alter_info.
 
3296
      To compare the new and old table definitions, we need to "prepare"
 
3297
      the new definition - transform it from parser output to a format
 
3298
      that describes the final table layout (all column defaults are
 
3299
      initialized, duplicate columns are removed). This is done by
 
3300
      mysql_prepare_create_table.  Unfortunately,
 
3301
      mysql_prepare_create_table performs its transformations
 
3302
      "in-place", that is, modifies the argument.  Since we would
 
3303
      like to keep compare_tables() idempotent (not altering any
 
3304
      of the arguments) we create a copy of alter_info here and
 
3305
      pass it to mysql_prepare_create_table, then use the result
 
3306
      to evaluate possibility of fast ALTER Table, and then
 
3307
      destroy the copy.
 
3308
    */
 
3309
    Alter_info tmp_alter_info(*alter_info, session->mem_root);
 
3310
    session= table->in_use;
 
3311
    uint32_t db_options= 0; /* not used */
 
3312
    /* Create the prepared information. */
 
3313
    if (mysql_prepare_create_table(session, create_info,
 
3314
                                   &tmp_alter_info,
 
3315
                                   (table->s->tmp_table != NO_TMP_TABLE),
 
3316
                                   &db_options,
 
3317
                                   table->file,
 
3318
                                   &ha_alter_info->key_info_buffer,
 
3319
                                   &ha_alter_info->key_count,
 
3320
                                   /* select_field_count */ 0))
 
3321
      return(true);
 
3322
    /* Allocate result buffers. */
 
3323
    if (! (ha_alter_info->index_drop_buffer=
 
3324
           (uint*) session->alloc(sizeof(uint32_t) * table->s->keys)) ||
 
3325
        ! (ha_alter_info->index_add_buffer=
 
3326
           (uint*) session->alloc(sizeof(uint32_t) *
 
3327
                              tmp_alter_info.key_list.elements)))
 
3328
      return(true);
 
3329
  }
 
3330
  /*
 
3331
    First we setup ha_alter_flags based on what was detected
 
3332
    by parser
 
3333
  */
 
3334
  setup_ha_alter_flags(alter_info, alter_flags);
 
3335
 
 
3336
 
 
3337
  /*
 
3338
    Some very basic checks. If number of fields changes, or the
 
3339
    handler, we need to run full ALTER Table. In the future
 
3340
    new fields can be added and old dropped without copy, but
 
3341
    not yet.
 
3342
 
 
3343
    Test also that engine was not given during ALTER Table, or
 
3344
    we are force to run regular alter table (copy).
 
3345
    E.g. ALTER Table tbl_name ENGINE=MyISAM.
 
3346
 
 
3347
    For the following ones we also want to run regular alter table:
 
3348
    ALTER Table tbl_name order_st BY ..
 
3349
    ALTER Table tbl_name CONVERT TO CHARACTER SET ..
 
3350
 
 
3351
    At the moment we can't handle altering temporary tables without a copy.
 
3352
    We also test if OPTIMIZE Table was given and was mapped to alter table.
 
3353
    In that case we always do full copy.
 
3354
 
 
3355
    There was a bug prior to mysql-4.0.25. Number of null fields was
 
3356
    calculated incorrectly. As a result frm and data files gets out of
 
3357
    sync after fast alter table. There is no way to determine by which
 
3358
    mysql version (in 4.0 and 4.1 branches) table was created, thus we
 
3359
    disable fast alter table for all tables created by mysql versions
 
3360
    prior to 5.0 branch.
 
3361
    See BUG#6236.
 
3362
  */
 
3363
  if (table->s->fields != alter_info->create_list.elements ||
 
3364
      table->s->db_type() != create_info->db_type ||
 
3365
      table->s->tmp_table ||
 
3366
      create_info->used_fields & HA_CREATE_USED_ENGINE ||
 
3367
      create_info->used_fields & HA_CREATE_USED_CHARSET ||
 
3368
      create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
 
3369
      create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
 
3370
      (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
 
3371
      order_num ||
 
3372
      !table->s->mysql_version)
 
3373
  {
 
3374
    *table_changes= IS_EQUAL_NO;
 
3375
    /*
 
3376
      Check what has changed and set alter_flags
 
3377
    */
 
3378
    if (table->s->fields < alter_info->create_list.elements)
 
3379
      *alter_flags|= HA_ADD_COLUMN;
 
3380
    else if (table->s->fields > alter_info->create_list.elements)
 
3381
      *alter_flags|= HA_DROP_COLUMN;
 
3382
    if (create_info->db_type != table->s->db_type() ||
 
3383
        create_info->used_fields & HA_CREATE_USED_ENGINE)
 
3384
      *alter_flags|= HA_ALTER_STORAGE_ENGINE;
 
3385
    if (create_info->used_fields & HA_CREATE_USED_CHARSET)
 
3386
      *alter_flags|= HA_CHANGE_CHARACTER_SET;
 
3387
    if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
 
3388
      *alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
 
3389
    if (alter_info->flags & ALTER_RECREATE)
 
3390
      *alter_flags|= HA_RECREATE;
 
3391
    /* TODO check for ADD/DROP FOREIGN KEY */
 
3392
    if (alter_info->flags & ALTER_FOREIGN_KEY)
 
3393
      *alter_flags|=  HA_ALTER_FOREIGN_KEY;
 
3394
  }
 
3395
  /*
 
3396
    Go through fields and check if the original ones are compatible
 
3397
    with new table.
 
3398
  */
 
3399
  for (f_ptr= table->field, new_field= new_field_it++;
 
3400
       (new_field && (field= *f_ptr));
 
3401
       f_ptr++, new_field= new_field_it++)
 
3402
  {
 
3403
    /* Make sure we have at least the default charset in use. */
 
3404
    if (!new_field->charset)
 
3405
      new_field->charset= create_info->default_table_charset;
 
3406
 
 
3407
    /* Don't pack rows in old tables if the user has requested this. */
 
3408
    if (create_info->row_type == ROW_TYPE_DYNAMIC ||
 
3409
        (new_field->flags & BLOB_FLAG) ||
 
3410
        (new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
 
3411
      create_info->table_options|= HA_OPTION_PACK_RECORD;
 
3412
 
 
3413
    /* Check how fields have been modified */
 
3414
    if (alter_info->flags & ALTER_CHANGE_COLUMN)
 
3415
    {
 
3416
      /* Evaluate changes bitmap and send to check_if_incompatible_data() */
 
3417
      if (!(table_changes_local= field->is_equal(new_field)))
 
3418
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
3419
 
 
3420
      /*
 
3421
        Check if the altered column is a stored virtual field.
 
3422
        TODO: Mark such a column with an alter flag only if
 
3423
        the expression functions are not equal.
 
3424
      */
 
3425
      if (field->is_stored && field->vcol_info)
 
3426
        *alter_flags|= HA_ALTER_STORED_VCOL;
 
3427
 
 
3428
      /* Check if field was renamed */
 
3429
      field->flags&= ~FIELD_IS_RENAMED;
 
3430
      if (my_strcasecmp(system_charset_info,
 
3431
                        field->field_name,
 
3432
                        new_field->field_name))
 
3433
      {
 
3434
        field->flags|= FIELD_IS_RENAMED;
 
3435
        *alter_flags|= HA_ALTER_COLUMN_NAME;
 
3436
      }
 
3437
 
 
3438
      *table_changes&= table_changes_local;
 
3439
      if (table_changes_local == IS_EQUAL_PACK_LENGTH)
 
3440
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
3441
 
 
3442
      /* Check that NULL behavior is same for old and new fields */
 
3443
      if ((new_field->flags & NOT_NULL_FLAG) !=
 
3444
          (uint32_t) (field->flags & NOT_NULL_FLAG))
 
3445
      {
 
3446
        *table_changes= IS_EQUAL_NO;
 
3447
        *alter_flags|= HA_ALTER_COLUMN_NULLABLE;
 
3448
      }
 
3449
    }
 
3450
 
 
3451
    /* Clear indexed marker */
 
3452
    field->flags&= ~FIELD_IN_ADD_INDEX;
 
3453
  }
 
3454
 
 
3455
  /*
 
3456
    Go through keys and check if the original ones are compatible
 
3457
    with new table.
 
3458
  */
 
3459
  KEY *table_key;
 
3460
  KEY *table_key_end= table->key_info + table->s->keys;
 
3461
  KEY *new_key;
 
3462
  KEY *new_key_end=
 
3463
       ha_alter_info->key_info_buffer + ha_alter_info->key_count;
 
3464
 
 
3465
  /*
 
3466
    Step through all keys of the old table and search matching new keys.
 
3467
  */
 
3468
  ha_alter_info->index_drop_count= 0;
 
3469
  ha_alter_info->index_add_count= 0;
 
3470
  for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
3471
  {
 
3472
    KEY_PART_INFO *table_part;
 
3473
    KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
 
3474
    KEY_PART_INFO *new_part;
 
3475
 
 
3476
    /* Search a new key with the same name. */
 
3477
    for (new_key= ha_alter_info->key_info_buffer;
 
3478
         new_key < new_key_end;
 
3479
         new_key++)
 
3480
    {
 
3481
      if (! strcmp(table_key->name, new_key->name))
 
3482
        break;
 
3483
    }
 
3484
    if (new_key >= new_key_end)
 
3485
    {
 
3486
      /* Key not found. Add the offset of the key to the drop buffer. */
 
3487
      ha_alter_info->index_drop_buffer
 
3488
           [ha_alter_info->index_drop_count++]=
 
3489
           table_key - table->key_info;
 
3490
      if (table_key->flags & HA_NOSAME)
 
3491
      {
 
3492
        /* Unique key. Check for "PRIMARY". */
 
3493
        if (is_primary_key(table_key))
 
3494
          *alter_flags|= HA_DROP_PK_INDEX;
 
3495
        else
 
3496
          *alter_flags|= HA_DROP_UNIQUE_INDEX;
 
3497
      }
 
3498
      else
 
3499
        *alter_flags|= HA_DROP_INDEX;
 
3500
      *table_changes= IS_EQUAL_NO;
 
3501
      continue;
 
3502
    }
 
3503
 
 
3504
    /* Check that the key types are compatible between old and new tables. */
 
3505
    if ((table_key->algorithm != new_key->algorithm) ||
 
3506
        ((table_key->flags & HA_KEYFLAG_MASK) !=
 
3507
         (new_key->flags & HA_KEYFLAG_MASK)) ||
 
3508
        (table_key->key_parts != new_key->key_parts))
 
3509
    {
 
3510
      if (table_key->flags & HA_NOSAME)
 
3511
      {
 
3512
        // Unique key. Check for "PRIMARY".
 
3513
        if (is_primary_key(table_key))
 
3514
          *alter_flags|= HA_ALTER_PK_INDEX;
 
3515
        else
 
3516
          *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
3517
      }
 
3518
      else
 
3519
        *alter_flags|= HA_ALTER_INDEX;
 
3520
      goto index_changed;
 
3521
    }
 
3522
 
 
3523
    /*
 
3524
      Check that the key parts remain compatible between the old and
 
3525
      new tables.
 
3526
    */
 
3527
    for (table_part= table_key->key_part, new_part= new_key->key_part;
 
3528
         table_part < table_part_end;
 
3529
         table_part++, new_part++)
 
3530
    {
 
3531
      /*
 
3532
        Key definition has changed if we are using a different field or
 
3533
        if the used key part length is different. We know that the fields
 
3534
        did not change. Comparing field numbers is sufficient.
 
3535
      */
 
3536
      if ((table_part->length != new_part->length) ||
 
3537
          (table_part->fieldnr - 1 != new_part->fieldnr))
 
3538
      {
 
3539
        if (table_key->flags & HA_NOSAME)
 
3540
        {
 
3541
          /* Unique key. Check for "PRIMARY" */
 
3542
          if (is_primary_key(table_key))
 
3543
            *alter_flags|= HA_ALTER_PK_INDEX;
 
3544
          else
 
3545
            *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
3546
        }
 
3547
        else
 
3548
          *alter_flags|= HA_ALTER_INDEX;
 
3549
        goto index_changed;
 
3550
      }
 
3551
    }
 
3552
    continue;
 
3553
 
 
3554
  index_changed:
 
3555
    /* Key modified. Add the offset of the key to both buffers. */
 
3556
    ha_alter_info->index_drop_buffer
 
3557
         [ha_alter_info->index_drop_count++]=
 
3558
         table_key - table->key_info;
 
3559
    ha_alter_info->index_add_buffer
 
3560
         [ha_alter_info->index_add_count++]=
 
3561
         new_key - ha_alter_info->key_info_buffer;
 
3562
    key_part= new_key->key_part;
 
3563
    end= key_part + new_key->key_parts;
 
3564
    for(; key_part != end; key_part++)
 
3565
    {
 
3566
      /* Mark field to be part of new key */
 
3567
      if ((field= table->field[key_part->fieldnr]))
 
3568
        field->flags|= FIELD_IN_ADD_INDEX;
 
3569
    }
 
3570
    *table_changes= IS_EQUAL_NO;
 
3571
  }
 
3572
  /*end of for (; table_key < table_key_end;) */
 
3573
 
 
3574
  /*
 
3575
    Step through all keys of the new table and find matching old keys.
 
3576
  */
 
3577
  for (new_key= ha_alter_info->key_info_buffer;
 
3578
       new_key < new_key_end;
 
3579
       new_key++)
 
3580
  {
 
3581
    /* Search an old key with the same name. */
 
3582
    for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
3583
    {
 
3584
      if (! strcmp(table_key->name, new_key->name))
 
3585
        break;
 
3586
    }
 
3587
    if (table_key >= table_key_end)
 
3588
    {
 
3589
      /* Key not found. Add the offset of the key to the add buffer. */
 
3590
      ha_alter_info->index_add_buffer
 
3591
           [ha_alter_info->index_add_count++]=
 
3592
           new_key - ha_alter_info->key_info_buffer;
 
3593
      key_part= new_key->key_part;
 
3594
      end= key_part + new_key->key_parts;
 
3595
      for(; key_part != end; key_part++)
 
3596
      {
 
3597
        /* Mark field to be part of new key */
 
3598
        if ((field= table->field[key_part->fieldnr]))
 
3599
          field->flags|= FIELD_IN_ADD_INDEX;
 
3600
      }
 
3601
      if (new_key->flags & HA_NOSAME)
 
3602
      {
 
3603
        /* Unique key. Check for "PRIMARY" */
 
3604
        if (is_primary_key(new_key))
 
3605
          *alter_flags|= HA_ADD_PK_INDEX;
 
3606
        else
 
3607
        *alter_flags|= HA_ADD_UNIQUE_INDEX;
 
3608
      }
 
3609
      else
 
3610
        *alter_flags|= HA_ADD_INDEX;
 
3611
      *table_changes= IS_EQUAL_NO;
 
3612
    }
 
3613
  }
 
3614
 
 
3615
  return(false);
 
3616
}
 
3617
 
 
3618
 
 
3619
/*
 
3620
  Manages enabling/disabling of indexes for ALTER Table
 
3621
 
 
3622
  SYNOPSIS
 
3623
    alter_table_manage_keys()
 
3624
      table                  Target table
 
3625
      indexes_were_disabled  Whether the indexes of the from table
 
3626
                             were disabled
 
3627
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
 
3628
 
 
3629
  RETURN VALUES
 
3630
    false  OK
 
3631
    true   Error
 
3632
*/
 
3633
 
 
3634
static
 
3635
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
 
3636
                             enum enum_enable_or_disable keys_onoff)
 
3637
{
 
3638
  int error= 0;
 
3639
  switch (keys_onoff) {
 
3640
  case ENABLE:
 
3641
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3642
    break;
 
3643
  case LEAVE_AS_IS:
 
3644
    if (!indexes_were_disabled)
 
3645
      break;
 
3646
    /* fall-through: disabled indexes */
 
3647
  case DISABLE:
 
3648
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3649
  }
 
3650
 
 
3651
  if (error == HA_ERR_WRONG_COMMAND)
 
3652
  {
 
3653
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3654
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3655
                        table->s->table_name.str);
 
3656
    error= 0;
 
3657
  } else if (error)
 
3658
    table->file->print_error(error, MYF(0));
 
3659
 
 
3660
  return(error);
 
3661
}
 
3662
 
 
3663
int create_temporary_table(Session *session,
 
3664
                           Table *table,
 
3665
                           char *new_db,
 
3666
                           char *tmp_name,
 
3667
                           HA_CREATE_INFO *create_info,
 
3668
                           Alter_info *alter_info,
 
3669
                           bool db_changed)
 
3670
{
 
3671
  int error;
 
3672
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
 
3673
  handlerton *old_db_type, *new_db_type;
 
3674
  old_db_type= table->s->db_type();
 
3675
  new_db_type= create_info->db_type;
 
3676
  /*
 
3677
    Handling of symlinked tables:
 
3678
    If no rename:
 
3679
      Create new data file and index file on the same disk as the
 
3680
      old data and index files.
 
3681
      Copy data.
 
3682
      Rename new data file over old data file and new index file over
 
3683
      old index file.
 
3684
      Symlinks are not changed.
 
3685
 
 
3686
   If rename:
 
3687
      Create new data file and index file on the same disk as the
 
3688
      old data and index files.  Create also symlinks to point at
 
3689
      the new tables.
 
3690
      Copy data.
 
3691
      At end, rename intermediate tables, and symlinks to intermediate
 
3692
      table, to final table name.
 
3693
      Remove old table and old symlinks
 
3694
 
 
3695
    If rename is made to another database:
 
3696
      Create new tables in new database.
 
3697
      Copy data.
 
3698
      Remove old table and symlinks.
 
3699
  */
 
3700
  if (db_changed)               // Ignore symlink if db changed
 
3701
  {
 
3702
    if (create_info->index_file_name)
 
3703
    {
 
3704
      /* Fix index_file_name to have 'tmp_name' as basename */
 
3705
      strcpy(index_file, tmp_name);
 
3706
      create_info->index_file_name=fn_same(index_file,
 
3707
                                           create_info->index_file_name,
 
3708
                                           1);
 
3709
    }
 
3710
    if (create_info->data_file_name)
 
3711
    {
 
3712
      /* Fix data_file_name to have 'tmp_name' as basename */
 
3713
      strcpy(data_file, tmp_name);
 
3714
      create_info->data_file_name=fn_same(data_file,
 
3715
                                          create_info->data_file_name,
 
3716
                                          1);
 
3717
    }
 
3718
  }
 
3719
  else
 
3720
    create_info->data_file_name=create_info->index_file_name=0;
 
3721
 
 
3722
  /*
 
3723
    Create a table with a temporary name.
 
3724
    We don't log the statement, it will be logged later.
 
3725
  */
 
3726
  error= mysql_create_table(session, new_db, tmp_name,
 
3727
                            create_info, alter_info, 1, 0);
 
3728
 
 
3729
  return(error);
 
3730
}
 
3731
 
 
3732
/*
 
3733
  Create a temporary table that reflects what an alter table operation
 
3734
  will accomplish.
 
3735
 
 
3736
  SYNOPSIS
 
3737
    create_altered_table()
 
3738
      session              Thread handle
 
3739
      table            The original table
 
3740
      create_info      Information from the parsing phase about new
 
3741
                       table properties.
 
3742
      alter_info       Lists of fields, keys to be changed, added
 
3743
                       or dropped.
 
3744
      db_change        Specifies if the table is moved to another database
 
3745
  RETURN
 
3746
    A temporary table with all changes
 
3747
    NULL if error
 
3748
  NOTES
 
3749
    The temporary table is created without storing it in any storage engine
 
3750
    and is opened only to get the table struct and frm file reference.
 
3751
*/
 
3752
Table *create_altered_table(Session *session,
 
3753
                            Table *table,
 
3754
                            char *new_db,
 
3755
                            HA_CREATE_INFO *create_info,
 
3756
                            Alter_info *alter_info,
 
3757
                            bool db_change)
 
3758
{
 
3759
  int error;
 
3760
  HA_CREATE_INFO altered_create_info(*create_info);
 
3761
  Table *altered_table;
 
3762
  char tmp_name[80];
 
3763
  char path[FN_REFLEN];
 
3764
 
 
3765
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64,
 
3766
           TMP_FILE_PREFIX, (unsigned long)current_pid, session->thread_id);
 
3767
  /* Safety fix for InnoDB */
 
3768
  if (lower_case_table_names)
 
3769
    my_casedn_str(files_charset_info, tmp_name);
 
3770
  altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
 
3771
 
 
3772
  if ((error= create_temporary_table(session, table, new_db, tmp_name,
 
3773
                                     &altered_create_info,
 
3774
                                     alter_info, db_change)))
 
3775
  {
 
3776
    return(NULL);
 
3777
  };
 
3778
 
 
3779
  build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
3780
                       FN_IS_TMP);
 
3781
  altered_table= open_temporary_table(session, path, new_db, tmp_name, 1,
 
3782
                                      OTM_ALTER);
 
3783
  return(altered_table);
 
3784
 
 
3785
  return(NULL);
 
3786
}
 
3787
 
 
3788
 
 
3789
/*
 
3790
  Perform a fast or on-line alter table
 
3791
 
 
3792
  SYNOPSIS
 
3793
    mysql_fast_or_online_alter_table()
 
3794
      session              Thread handle
 
3795
      table            The original table
 
3796
      altered_table    A temporary table showing how we will change table
 
3797
      create_info      Information from the parsing phase about new
 
3798
                       table properties.
 
3799
      alter_info       Storage place for data used during different phases
 
3800
      ha_alter_flags   Bitmask that shows what will be changed
 
3801
      keys_onoff       Specifies if keys are to be enabled/disabled
 
3802
  RETURN
 
3803
     0  OK
 
3804
    >0  An error occured during the on-line alter table operation
 
3805
    -1  Error when re-opening table
 
3806
  NOTES
 
3807
    If mysql_alter_table does not need to copy the table, it is
 
3808
    either a fast alter table where the storage engine does not
 
3809
    need to know about the change, only the frm will change,
 
3810
    or the storage engine supports performing the alter table
 
3811
    operation directly, on-line without mysql having to copy
 
3812
    the table.
 
3813
*/
 
3814
int mysql_fast_or_online_alter_table(Session *session,
 
3815
                                     Table *table,
 
3816
                                     Table *altered_table,
 
3817
                                     HA_CREATE_INFO *create_info,
 
3818
                                     HA_ALTER_INFO *alter_info,
 
3819
                                     HA_ALTER_FLAGS *ha_alter_flags,
 
3820
                                     enum enum_enable_or_disable keys_onoff)
 
3821
{
 
3822
  int error= 0;
 
3823
  bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
 
3824
  Table *t_table;
 
3825
 
 
3826
  if (online)
 
3827
  {
 
3828
   /*
 
3829
      Tell the handler to prepare for the online alter
 
3830
    */
 
3831
    if ((error= table->file->alter_table_phase1(session,
 
3832
                                                altered_table,
 
3833
                                                create_info,
 
3834
                                                alter_info,
 
3835
                                                ha_alter_flags)))
 
3836
    {
 
3837
      goto err;
 
3838
    }
 
3839
 
 
3840
    /*
 
3841
       Tell the storage engine to perform the online alter table
 
3842
       TODO:
 
3843
       if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
 
3844
       we need to wrap the next call with a DDL lock.
 
3845
     */
 
3846
    if ((error= table->file->alter_table_phase2(session,
 
3847
                                                altered_table,
 
3848
                                                create_info,
 
3849
                                                alter_info,
 
3850
                                                ha_alter_flags)))
 
3851
    {
 
3852
      goto err;
 
3853
    }
 
3854
  }
 
3855
  /*
 
3856
    The final .frm file is already created as a temporary file
 
3857
    and will be renamed to the original table name.
 
3858
  */
 
3859
  pthread_mutex_lock(&LOCK_open);
 
3860
  wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
3861
  alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
3862
                          keys_onoff);
 
3863
  close_data_files_and_morph_locks(session,
 
3864
                                   table->pos_in_table_list->db,
 
3865
                                   table->pos_in_table_list->table_name);
 
3866
  if (mysql_rename_table(NULL,
 
3867
                         altered_table->s->db.str,
 
3868
                         altered_table->s->table_name.str,
 
3869
                         table->s->db.str,
 
3870
                         table->s->table_name.str, FN_FROM_IS_TMP))
 
3871
  {
 
3872
    error= 1;
 
3873
    pthread_mutex_unlock(&LOCK_open);
 
3874
    goto err;
 
3875
  }
 
3876
  broadcast_refresh();
 
3877
  pthread_mutex_unlock(&LOCK_open);
 
3878
 
 
3879
  /*
 
3880
    The ALTER Table is always in its own transaction.
 
3881
    Commit must not be called while LOCK_open is locked. It could call
 
3882
    wait_if_global_read_lock(), which could create a deadlock if called
 
3883
    with LOCK_open.
 
3884
  */
 
3885
  error= ha_autocommit_or_rollback(session, 0);
 
3886
 
 
3887
  if (ha_commit(session))
 
3888
    error=1;
 
3889
  if (error)
 
3890
    goto err;
 
3891
  if (online)
 
3892
  {
 
3893
    pthread_mutex_lock(&LOCK_open);
 
3894
    if (reopen_table(table))
 
3895
    {
 
3896
      error= -1;
 
3897
      goto err;
 
3898
    }
 
3899
    pthread_mutex_unlock(&LOCK_open);
 
3900
    t_table= table;
 
3901
 
 
3902
   /*
 
3903
      Tell the handler that the changed frm is on disk and table
 
3904
      has been re-opened
 
3905
   */
 
3906
    if ((error= t_table->file->alter_table_phase3(session, t_table)))
 
3907
    {
 
3908
      goto err;
 
3909
    }
 
3910
 
 
3911
    /*
 
3912
      We are going to reopen table down on the road, so we have to restore
 
3913
      state of the Table object which we used for obtaining of handler
 
3914
      object to make it suitable for reopening.
 
3915
    */
 
3916
    assert(t_table == table);
 
3917
    table->open_placeholder= 1;
 
3918
    pthread_mutex_lock(&LOCK_open);
 
3919
    close_handle_and_leave_table_as_lock(table);
 
3920
    pthread_mutex_unlock(&LOCK_open);
 
3921
  }
 
3922
 
 
3923
 err:
 
3924
  if (error)
 
3925
    return(error);
 
3926
  return 0;
 
3927
}
 
3928
 
 
3929
 
 
3930
/**
 
3931
  Prepare column and key definitions for CREATE TABLE in ALTER Table.
 
3932
 
 
3933
  This function transforms parse output of ALTER Table - lists of
 
3934
  columns and keys to add, drop or modify into, essentially,
 
3935
  CREATE TABLE definition - a list of columns and keys of the new
 
3936
  table. While doing so, it also performs some (bug not all)
 
3937
  semantic checks.
 
3938
 
 
3939
  This function is invoked when we know that we're going to
 
3940
  perform ALTER Table via a temporary table -- i.e. fast ALTER Table
 
3941
  is not possible, perhaps because the ALTER statement contains
 
3942
  instructions that require change in table data, not only in
 
3943
  table definition or indexes.
 
3944
 
 
3945
  @param[in,out]  session         thread handle. Used as a memory pool
 
3946
                              and source of environment information.
 
3947
  @param[in]      table       the source table, open and locked
 
3948
                              Used as an interface to the storage engine
 
3949
                              to acquire additional information about
 
3950
                              the original table.
 
3951
  @param[in,out]  create_info A blob with CREATE/ALTER Table
 
3952
                              parameters
 
3953
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
 
3954
                              Originally create_info was used only in
 
3955
                              CREATE TABLE and alter_info only in ALTER Table.
 
3956
                              But since ALTER might end-up doing CREATE,
 
3957
                              this distinction is gone and we just carry
 
3958
                              around two structures.
 
3959
 
 
3960
  @return
 
3961
    Fills various create_info members based on information retrieved
 
3962
    from the storage engine.
 
3963
    Sets create_info->varchar if the table has a VARCHAR column.
 
3964
    Prepares alter_info->create_list and alter_info->key_list with
 
3965
    columns and keys of the new table.
 
3966
  @retval true   error, out of memory or a semantical error in ALTER
 
3967
                 Table instructions
 
3968
  @retval false  success
 
3969
*/
 
3970
 
 
3971
static bool
 
3972
mysql_prepare_alter_table(Session *session, Table *table,
 
3973
                          HA_CREATE_INFO *create_info,
 
3974
                          Alter_info *alter_info)
 
3975
{
 
3976
  /* New column definitions are added here */
 
3977
  List<Create_field> new_create_list;
 
3978
  /* New key definitions are added here */
 
3979
  List<Key> new_key_list;
 
3980
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
 
3981
  List_iterator<Create_field> def_it(alter_info->create_list);
 
3982
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
 
3983
  List_iterator<Key> key_it(alter_info->key_list);
 
3984
  List_iterator<Create_field> find_it(new_create_list);
 
3985
  List_iterator<Create_field> field_it(new_create_list);
 
3986
  List<Key_part_spec> key_parts;
 
3987
  uint32_t db_create_options= (table->s->db_create_options
 
3988
                           & ~(HA_OPTION_PACK_RECORD));
 
3989
  uint32_t used_fields= create_info->used_fields;
 
3990
  KEY *key_info=table->key_info;
 
3991
  bool rc= true;
 
3992
 
 
3993
 
 
3994
  create_info->varchar= false;
 
3995
  /* Let new create options override the old ones */
 
3996
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
 
3997
    create_info->min_rows= table->s->min_rows;
 
3998
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
 
3999
    create_info->max_rows= table->s->max_rows;
 
4000
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
 
4001
    create_info->avg_row_length= table->s->avg_row_length;
 
4002
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
4003
    create_info->block_size= table->s->block_size;
 
4004
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
4005
    create_info->default_table_charset= table->s->table_charset;
 
4006
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
4007
    {
 
4008
    /* Table has an autoincrement, copy value to new table */
 
4009
    table->file->info(HA_STATUS_AUTO);
 
4010
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
 
4011
  }
 
4012
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
4013
    create_info->key_block_size= table->s->key_block_size;
 
4014
 
 
4015
  restore_record(table, s->default_values);     // Empty record for DEFAULT
 
4016
  Create_field *def;
 
4017
 
 
4018
    /*
 
4019
    First collect all fields from table which isn't in drop_list
 
4020
    */
 
4021
  Field **f_ptr,*field;
 
4022
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
 
4023
    {
 
4024
    /* Check if field should be dropped */
 
4025
    Alter_drop *drop;
 
4026
    drop_it.rewind();
 
4027
    while ((drop=drop_it++))
 
4028
    {
 
4029
      if (drop->type == Alter_drop::COLUMN &&
 
4030
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
 
4031
    {
 
4032
        /* Reset auto_increment value if it was dropped */
 
4033
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
4034
            !(used_fields & HA_CREATE_USED_AUTO))
 
4035
      {
 
4036
          create_info->auto_increment_value=0;
 
4037
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
4038
      }
 
4039
        break;
 
4040
    }
 
4041
  }
 
4042
    if (drop)
 
4043
      {
 
4044
      drop_it.remove();
 
4045
      continue;
 
4046
    }
 
4047
    /* Check if field is changed */
 
4048
    def_it.rewind();
 
4049
    while ((def=def_it++))
 
4050
    {
 
4051
      if (def->change &&
 
4052
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
4053
        break;
 
4054
    }
 
4055
    if (def)
 
4056
    {                                           // Field is changed
 
4057
      def->field=field;
 
4058
      if (field->is_stored != def->is_stored)
 
4059
      {
 
4060
        my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
 
4061
                 MYF(0),
 
4062
                 "Changing the STORED status");
 
4063
        goto err;
 
4064
      }
 
4065
      if (!def->after)
 
4066
        {
 
4067
        new_create_list.push_back(def);
 
4068
        def_it.remove();
 
4069
        }
 
4070
      }
 
4071
      else
 
4072
      {
 
4073
      /*
 
4074
        This field was not dropped and not changed, add it to the list
 
4075
        for the new table.
 
4076
      */
 
4077
      def= new Create_field(field, field);
 
4078
      new_create_list.push_back(def);
 
4079
      alter_it.rewind();                        // Change default if ALTER
 
4080
      Alter_column *alter;
 
4081
      while ((alter=alter_it++))
 
4082
        {
 
4083
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
4084
          break;
 
4085
        }
 
4086
      if (alter)
 
4087
        {
 
4088
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
 
4089
        {
 
4090
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
4091
          goto err;
 
4092
        }
 
4093
        if ((def->def=alter->def))              // Use new default
 
4094
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
 
4095
        else
 
4096
          def->flags|= NO_DEFAULT_VALUE_FLAG;
 
4097
        alter_it.remove();
 
4098
      }
 
4099
    }
 
4100
  }
 
4101
  def_it.rewind();
 
4102
  while ((def=def_it++))                        // Add new columns
 
4103
  {
 
4104
    if (def->change && ! def->field)
 
4105
    {
 
4106
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
4107
      goto err;
 
4108
    }
 
4109
      /*
 
4110
      Check that the DATE/DATETIME not null field we are going to add is
 
4111
      either has a default value or the '0000-00-00' is allowed by the
 
4112
      set sql mode.
 
4113
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
4114
      flag to allow ALTER Table only if the table to be altered is empty.
 
4115
      */
 
4116
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
4117
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
4118
         !alter_info->datetime_field &&
 
4119
         !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
4120
         session->variables.sql_mode & MODE_NO_ZERO_DATE)
 
4121
    {
 
4122
        alter_info->datetime_field= def;
 
4123
        alter_info->error_if_not_empty= true;
 
4124
    }
 
4125
    if (!def->after)
 
4126
      new_create_list.push_back(def);
 
4127
    else if (def->after == first_keyword)
 
4128
      new_create_list.push_front(def);
 
4129
    else
 
4130
    {
 
4131
      Create_field *find;
 
4132
      find_it.rewind();
 
4133
      while ((find=find_it++))                  // Add new columns
 
4134
      {
 
4135
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
4136
          break;
 
4137
  }
 
4138
      if (!find)
 
4139
  {
 
4140
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
4141
    goto err;
 
4142
  }
 
4143
      find_it.after(def);                       // Put element after this
 
4144
      /*
 
4145
        XXX: hack for Bug#28427.
 
4146
        If column order has changed, force OFFLINE ALTER Table
 
4147
        without querying engine capabilities.  If we ever have an
 
4148
        engine that supports online ALTER Table CHANGE COLUMN
 
4149
        <name> AFTER <name1> (Falcon?), this fix will effectively
 
4150
        disable the capability.
 
4151
        TODO: detect the situation in compare_tables, behave based
 
4152
        on engine capabilities.
 
4153
      */
 
4154
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
4155
      {
 
4156
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
4157
        goto err;
 
4158
      }
 
4159
      alter_info->build_method= HA_BUILD_OFFLINE;
 
4160
    }
 
4161
  }
 
4162
  if (alter_info->alter_list.elements)
 
4163
  {
 
4164
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
4165
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
4166
    goto err;
 
4167
    }
 
4168
  if (!new_create_list.elements)
 
4169
    {
 
4170
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
 
4171
               MYF(0));
 
4172
    goto err;
 
4173
    }
 
4174
 
 
4175
    /*
 
4176
    Collect all keys which isn't in drop list. Add only those
 
4177
    for which some fields exists.
 
4178
    */
 
4179
 
 
4180
  for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
 
4181
    {
 
4182
    char *key_name= key_info->name;
 
4183
    Alter_drop *drop;
 
4184
    drop_it.rewind();
 
4185
    while ((drop=drop_it++))
 
4186
      {
 
4187
      if (drop->type == Alter_drop::KEY &&
 
4188
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
4189
        break;
 
4190
      }
 
4191
    if (drop)
 
4192
        {
 
4193
      drop_it.remove();
 
4194
      continue;
 
4195
    }
 
4196
 
 
4197
    KEY_PART_INFO *key_part= key_info->key_part;
 
4198
    key_parts.empty();
 
4199
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
4200
    {
 
4201
      if (!key_part->field)
 
4202
        continue;                               // Wrong field (from UNIREG)
 
4203
      const char *key_part_name=key_part->field->field_name;
 
4204
      Create_field *cfield;
 
4205
      field_it.rewind();
 
4206
      while ((cfield=field_it++))
 
4207
    {
 
4208
        if (cfield->change)
 
4209
    {
 
4210
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
4211
                             cfield->change))
 
4212
            break;
 
4213
        }
 
4214
        else if (!my_strcasecmp(system_charset_info,
 
4215
                                key_part_name, cfield->field_name))
 
4216
          break;
 
4217
      }
 
4218
      if (!cfield)
 
4219
        continue;                               // Field is removed
 
4220
      uint32_t key_part_length=key_part->length;
 
4221
      if (cfield->field)                        // Not new field
 
4222
      {
 
4223
        /*
 
4224
          If the field can't have only a part used in a key according to its
 
4225
          new type, or should not be used partially according to its
 
4226
          previous type, or the field length is less than the key part
 
4227
          length, unset the key part length.
 
4228
 
 
4229
          We also unset the key part length if it is the same as the
 
4230
          old field's length, so the whole new field will be used.
 
4231
 
 
4232
          BLOBs may have cfield->length == 0, which is why we test it before
 
4233
          checking whether cfield->length < key_part_length (in chars).
 
4234
         */
 
4235
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
4236
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
4237
            (cfield->field->field_length == key_part_length &&
 
4238
             !f_is_blob(key_part->key_type)) ||
 
4239
            (cfield->length && (cfield->length < key_part_length /
 
4240
                                key_part->field->charset()->mbmaxlen)))
 
4241
          key_part_length= 0;                   // Use whole field
 
4242
      }
 
4243
      key_part_length /= key_part->field->charset()->mbmaxlen;
 
4244
      key_parts.push_back(new Key_part_spec(cfield->field_name,
 
4245
                                            strlen(cfield->field_name),
 
4246
                                            key_part_length));
 
4247
    }
 
4248
    if (key_parts.elements)
 
4249
    {
 
4250
      KEY_CREATE_INFO key_create_info;
 
4251
      Key *key;
 
4252
      enum Key::Keytype key_type;
 
4253
      memset(&key_create_info, 0, sizeof(key_create_info));
 
4254
 
 
4255
      key_create_info.algorithm= key_info->algorithm;
 
4256
      if (key_info->flags & HA_USES_BLOCK_SIZE)
 
4257
        key_create_info.block_size= key_info->block_size;
 
4258
      if (key_info->flags & HA_USES_COMMENT)
 
4259
        key_create_info.comment= key_info->comment;
 
4260
 
 
4261
      if (key_info->flags & HA_NOSAME)
 
4262
      {
 
4263
        if (is_primary_key_name(key_name))
 
4264
          key_type= Key::PRIMARY;
 
4265
        else
 
4266
          key_type= Key::UNIQUE;
 
4267
      }
 
4268
      else
 
4269
        key_type= Key::MULTIPLE;
 
4270
 
 
4271
      key= new Key(key_type, key_name, strlen(key_name),
 
4272
                   &key_create_info,
 
4273
                   test(key_info->flags & HA_GENERATED_KEY),
 
4274
                   key_parts);
 
4275
      new_key_list.push_back(key);
 
4276
    }
 
4277
  }
 
4278
  {
 
4279
    Key *key;
 
4280
    while ((key=key_it++))                      // Add new keys
 
4281
    {
 
4282
      if (key->type == Key::FOREIGN_KEY &&
 
4283
          ((Foreign_key *)key)->validate(new_create_list))
 
4284
        goto err;
 
4285
      if (key->type != Key::FOREIGN_KEY)
 
4286
        new_key_list.push_back(key);
 
4287
      if (key->name.str && is_primary_key_name(key->name.str))
 
4288
      {
 
4289
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
4290
        goto err;
 
4291
      }
 
4292
    }
 
4293
  }
 
4294
 
 
4295
  if (alter_info->drop_list.elements)
 
4296
  {
 
4297
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
4298
             alter_info->drop_list.head()->name);
 
4299
    goto err;
 
4300
  }
 
4301
  if (alter_info->alter_list.elements)
 
4302
  {
 
4303
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
4304
             alter_info->alter_list.head()->name);
 
4305
    goto err;
 
4306
  }
 
4307
 
 
4308
  if (!create_info->comment.str)
 
4309
  {
 
4310
    create_info->comment.str= table->s->comment.str;
 
4311
    create_info->comment.length= table->s->comment.length;
 
4312
  }
 
4313
 
 
4314
  table->file->update_create_info(create_info);
 
4315
  if ((create_info->table_options &
 
4316
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
 
4317
      (used_fields & HA_CREATE_USED_PACK_KEYS))
 
4318
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
 
4319
  if (create_info->table_options &
 
4320
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
 
4321
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
 
4322
  if (create_info->table_options &
 
4323
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
 
4324
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
 
4325
                          HA_OPTION_NO_DELAY_KEY_WRITE);
 
4326
  create_info->table_options|= db_create_options;
 
4327
 
 
4328
  if (table->s->tmp_table)
 
4329
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
4330
 
 
4331
  rc= false;
 
4332
  alter_info->create_list.swap(new_create_list);
 
4333
  alter_info->key_list.swap(new_key_list);
 
4334
err:
 
4335
  return(rc);
 
4336
}
 
4337
 
 
4338
 
 
4339
/*
 
4340
  Alter table
 
4341
 
 
4342
  SYNOPSIS
 
4343
    mysql_alter_table()
 
4344
      session              Thread handle
 
4345
      new_db           If there is a RENAME clause
 
4346
      new_name         If there is a RENAME clause
 
4347
      create_info      Information from the parsing phase about new
 
4348
                       table properties.
 
4349
      table_list       The table to change.
 
4350
      alter_info       Lists of fields, keys to be changed, added
 
4351
                       or dropped.
 
4352
      order_num        How many order_st BY fields has been specified.
 
4353
      order            List of fields to order_st BY.
 
4354
      ignore           Whether we have ALTER IGNORE Table
 
4355
 
 
4356
  DESCRIPTION
 
4357
    This is a veery long function and is everything but the kitchen sink :)
 
4358
    It is used to alter a table and not only by ALTER Table but also
 
4359
    CREATE|DROP INDEX are mapped on this function.
 
4360
 
 
4361
    When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
 
4362
    or both, then this function short cuts its operation by renaming
 
4363
    the table and/or enabling/disabling the keys. In this case, the FRM is
 
4364
    not changed, directly by mysql_alter_table. However, if there is a
 
4365
    RENAME + change of a field, or an index, the short cut is not used.
 
4366
    See how `create_list` is used to generate the new FRM regarding the
 
4367
    structure of the fields. The same is done for the indices of the table.
 
4368
 
 
4369
    Important is the fact, that this function tries to do as little work as
 
4370
    possible, by finding out whether a intermediate table is needed to copy
 
4371
    data into and when finishing the altering to use it as the original table.
 
4372
    For this reason the function compare_tables() is called, which decides
 
4373
    based on all kind of data how similar are the new and the original
 
4374
    tables.
 
4375
 
 
4376
  RETURN VALUES
 
4377
    false  OK
 
4378
    true   Error
 
4379
*/
 
4380
 
 
4381
bool mysql_alter_table(Session *session,char *new_db, char *new_name,
 
4382
                       HA_CREATE_INFO *create_info,
 
4383
                       TableList *table_list,
 
4384
                       Alter_info *alter_info,
 
4385
                       uint32_t order_num, order_st *order, bool ignore)
 
4386
{
 
4387
  Table *table, *new_table=0, *name_lock= 0;;
 
4388
  string new_name_str;
 
4389
  int error= 0;
 
4390
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
 
4391
  char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
 
4392
  char path[FN_REFLEN];
 
4393
  ha_rows copied= 0,deleted= 0;
 
4394
  handlerton *old_db_type, *new_db_type, *save_old_db_type;
 
4395
 
 
4396
  new_name_buff[0]= '\0';
 
4397
 
 
4398
  if (table_list && table_list->schema_table)
 
4399
  {
 
4400
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
4401
    return(true);
 
4402
  }
 
4403
 
 
4404
  /*
 
4405
    Assign variables table_name, new_name, db, new_db, path
 
4406
    to simplify further comparisons: we want to see if it's a RENAME
 
4407
    later just by comparing the pointers, avoiding the need for strcmp.
 
4408
  */
 
4409
  session->set_proc_info("init");
 
4410
  table_name=table_list->table_name;
 
4411
  alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
 
4412
  db=table_list->db;
 
4413
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
 
4414
    new_db= db;
 
4415
  build_table_filename(path, sizeof(path), db, table_name, "", 0);
 
4416
 
 
4417
  mysql_ha_rm_tables(session, table_list, false);
 
4418
 
 
4419
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
4420
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
4421
    /* Conditionally writes to binlog. */
 
4422
    return(mysql_discard_or_import_tablespace(session,table_list,
 
4423
                                              alter_info->tablespace_op));
 
4424
  ostringstream oss;
 
4425
  oss << drizzle_data_home << "/" << db << "/" << table_name << reg_ext;
 
4426
 
 
4427
  (void) unpack_filename(new_name_buff, oss.str().c_str());
 
4428
  /*
 
4429
    If this is just a rename of a view, short cut to the
 
4430
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
4431
    2) unlock LOCK_open.
 
4432
    This is a copy-paste added to make sure
 
4433
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
 
4434
    as an independent branch in mysql_execute_command. The need
 
4435
    for a copy-paste arose because the main code flow of ALTER Table
 
4436
    ... RENAME tries to use open_ltable, which does not work for views
 
4437
    (open_ltable was never modified to merge table lists of child tables
 
4438
    into the main table list, like open_tables does).
 
4439
    This code is wrong and will be removed, please do not copy.
 
4440
  */
 
4441
 
 
4442
  if (!(table= open_n_lock_single_table(session, table_list, TL_WRITE_ALLOW_READ)))
 
4443
    return(true);
 
4444
  table->use_all_columns();
 
4445
 
 
4446
  /* Check that we are not trying to rename to an existing table */
 
4447
  if (new_name)
 
4448
  {
 
4449
    strcpy(new_name_buff,new_name);
 
4450
    strcpy(new_alias= new_alias_buff, new_name);
 
4451
    if (lower_case_table_names)
 
4452
    {
 
4453
      if (lower_case_table_names != 2)
 
4454
      {
 
4455
        my_casedn_str(files_charset_info, new_name_buff);
 
4456
        new_alias= new_name;                    // Create lower case table name
 
4457
      }
 
4458
      my_casedn_str(files_charset_info, new_name);
 
4459
    }
 
4460
    if (new_db == db &&
 
4461
        !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
4462
    {
 
4463
      /*
 
4464
        Source and destination table names are equal: make later check
 
4465
        easier.
 
4466
      */
 
4467
      new_alias= new_name= table_name;
 
4468
    }
 
4469
    else
 
4470
    {
 
4471
      if (table->s->tmp_table != NO_TMP_TABLE)
 
4472
      {
 
4473
        if (find_temporary_table(session,new_db,new_name_buff))
 
4474
        {
 
4475
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
4476
          return(true);
 
4477
        }
 
4478
      }
 
4479
      else
 
4480
      {
 
4481
        if (lock_table_name_if_not_cached(session, new_db, new_name, &name_lock))
 
4482
          return(true);
 
4483
        if (!name_lock)
 
4484
        {
 
4485
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
4486
          return(true);
 
4487
        }
 
4488
 
 
4489
        build_table_filename(new_name_buff, sizeof(new_name_buff),
 
4490
                             new_db, new_name_buff, reg_ext, 0);
 
4491
        if (!access(new_name_buff, F_OK))
 
4492
        {
 
4493
          /* Table will be closed in do_command() */
 
4494
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
4495
          goto err;
 
4496
        }
 
4497
      }
 
4498
    }
 
4499
  }
 
4500
  else
 
4501
  {
 
4502
    new_alias= (lower_case_table_names == 2) ? alias : table_name;
 
4503
    new_name= table_name;
 
4504
  }
 
4505
 
 
4506
  old_db_type= table->s->db_type();
 
4507
  if (!create_info->db_type)
 
4508
  {
 
4509
    create_info->db_type= old_db_type;
 
4510
  }
 
4511
 
 
4512
  if (check_engine(session, new_name, create_info))
 
4513
    goto err;
 
4514
  new_db_type= create_info->db_type;
 
4515
 
 
4516
  if (new_db_type != old_db_type &&
 
4517
      !table->file->can_switch_engines())
 
4518
  {
 
4519
    assert(0);
 
4520
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
 
4521
    goto err;
 
4522
  }
 
4523
 
 
4524
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
4525
    create_info->row_type= table->s->row_type;
 
4526
 
 
4527
  if (ha_check_storage_engine_flag(old_db_type, HTON_BIT_ALTER_NOT_SUPPORTED) ||
 
4528
      ha_check_storage_engine_flag(new_db_type, HTON_BIT_ALTER_NOT_SUPPORTED))
 
4529
  {
 
4530
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
4531
    goto err;
 
4532
  }
 
4533
 
 
4534
  session->set_proc_info("setup");
 
4535
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
 
4536
      !table->s->tmp_table) // no need to touch frm
 
4537
  {
 
4538
    switch (alter_info->keys_onoff) {
 
4539
    case LEAVE_AS_IS:
 
4540
      break;
 
4541
    case ENABLE:
 
4542
      /*
 
4543
        wait_while_table_is_used() ensures that table being altered is
 
4544
        opened only by this thread and that Table::TABLE_SHARE::version
 
4545
        of Table object corresponding to this table is 0.
 
4546
        The latter guarantees that no DML statement will open this table
 
4547
        until ALTER Table finishes (i.e. until close_thread_tables())
 
4548
        while the fact that the table is still open gives us protection
 
4549
        from concurrent DDL statements.
 
4550
      */
 
4551
      pthread_mutex_lock(&LOCK_open);
 
4552
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
4553
      pthread_mutex_unlock(&LOCK_open);
 
4554
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4555
      /* COND_refresh will be signaled in close_thread_tables() */
 
4556
      break;
 
4557
    case DISABLE:
 
4558
      pthread_mutex_lock(&LOCK_open);
 
4559
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
4560
      pthread_mutex_unlock(&LOCK_open);
 
4561
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4562
      /* COND_refresh will be signaled in close_thread_tables() */
 
4563
      break;
 
4564
    default:
 
4565
      assert(false);
 
4566
      error= 0;
 
4567
      break;
 
4568
    }
 
4569
    if (error == HA_ERR_WRONG_COMMAND)
 
4570
    {
 
4571
      error= 0;
 
4572
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
4573
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
4574
                          table->alias);
 
4575
    }
 
4576
 
 
4577
    pthread_mutex_lock(&LOCK_open);
 
4578
    /*
 
4579
      Unlike to the above case close_cached_table() below will remove ALL
 
4580
      instances of Table from table cache (it will also remove table lock
 
4581
      held by this thread). So to make actual table renaming and writing
 
4582
      to binlog atomic we have to put them into the same critical section
 
4583
      protected by LOCK_open mutex. This also removes gap for races between
 
4584
      access() and mysql_rename_table() calls.
 
4585
    */
 
4586
 
 
4587
    if (!error && (new_name != table_name || new_db != db))
 
4588
    {
 
4589
      session->set_proc_info("rename");
 
4590
      /*
 
4591
        Then do a 'simple' rename of the table. First we need to close all
 
4592
        instances of 'source' table.
 
4593
      */
 
4594
      close_cached_table(session, table);
 
4595
      /*
 
4596
        Then, we want check once again that target table does not exist.
 
4597
        Actually the order of these two steps does not matter since
 
4598
        earlier we took name-lock on the target table, so we do them
 
4599
        in this particular order only to be consistent with 5.0, in which
 
4600
        we don't take this name-lock and where this order really matters.
 
4601
        TODO: Investigate if we need this access() check at all.
 
4602
      */
 
4603
      if (!access(new_name_buff,F_OK))
 
4604
      {
 
4605
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
4606
        error= -1;
 
4607
      }
 
4608
      else
 
4609
      {
 
4610
        *fn_ext(new_name)=0;
 
4611
        if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
 
4612
          error= -1;
 
4613
        else if (0)
 
4614
      {
 
4615
          mysql_rename_table(old_db_type, new_db, new_alias, db,
 
4616
                             table_name, 0);
 
4617
          error= -1;
 
4618
      }
 
4619
    }
 
4620
  }
 
4621
 
 
4622
    if (error == HA_ERR_WRONG_COMMAND)
 
4623
  {
 
4624
      error= 0;
 
4625
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
4626
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
4627
                          table->alias);
 
4628
  }
 
4629
 
 
4630
    if (!error)
 
4631
    {
 
4632
      write_bin_log(session, true, session->query, session->query_length);
 
4633
      session->my_ok();
 
4634
  }
 
4635
    else if (error > 0)
 
4636
  {
 
4637
      table->file->print_error(error, MYF(0));
 
4638
      error= -1;
 
4639
    }
 
4640
    if (name_lock)
 
4641
      unlink_open_table(session, name_lock, false);
 
4642
    pthread_mutex_unlock(&LOCK_open);
 
4643
    table_list->table= NULL;                    // For query cache
 
4644
    return(error);
 
4645
  }
 
4646
 
 
4647
  /* We have to do full alter table. */
 
4648
 
 
4649
    /*
 
4650
    If the old table had partitions and we are doing ALTER Table ...
 
4651
    engine= <new_engine>, the new table must preserve the original
 
4652
    partitioning. That means that the new engine is still the
 
4653
    partitioning engine, not the engine specified in the parser.
 
4654
    This is discovered  in prep_alter_part_table, which in such case
 
4655
    updates create_info->db_type.
 
4656
    Now we need to update the stack copy of create_info->db_type,
 
4657
    as otherwise we won't be able to correctly move the files of the
 
4658
    temporary table to the result table files.
 
4659
  */
 
4660
  new_db_type= create_info->db_type;
 
4661
 
 
4662
  if (mysql_prepare_alter_table(session, table, create_info, alter_info))
 
4663
      goto err;
 
4664
 
 
4665
  set_table_default_charset(session, create_info, db);
 
4666
 
 
4667
  if (session->variables.old_alter_table
 
4668
      || (table->s->db_type() != create_info->db_type)
 
4669
     )
 
4670
  {
 
4671
    if (alter_info->build_method == HA_BUILD_ONLINE)
 
4672
    {
 
4673
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
4674
      goto err;
 
4675
    }
 
4676
    alter_info->build_method= HA_BUILD_OFFLINE;
 
4677
  }
 
4678
 
 
4679
  if (alter_info->build_method != HA_BUILD_OFFLINE)
 
4680
  {
 
4681
    Table *altered_table= 0;
 
4682
    HA_ALTER_INFO ha_alter_info;
 
4683
    HA_ALTER_FLAGS ha_alter_flags;
 
4684
    uint32_t table_changes= IS_EQUAL_YES;
 
4685
    bool need_copy_table= true;
 
4686
    /* Check how much the tables differ. */
 
4687
    if (compare_tables(session, table, alter_info,
 
4688
                       create_info, order_num,
 
4689
                       &ha_alter_flags,
 
4690
                       &ha_alter_info,
 
4691
                       &table_changes))
 
4692
    {
 
4693
      return(true);
 
4694
    }
 
4695
 
 
4696
    /*
 
4697
      Check if storage engine supports altering the table
 
4698
      on-line.
 
4699
    */
 
4700
 
 
4701
 
 
4702
    /*
 
4703
      If table is not renamed, changed database and
 
4704
      some change was detected then check if engine
 
4705
      can do the change on-line
 
4706
    */
 
4707
    if (new_name == table_name && new_db == db &&
 
4708
        ha_alter_flags.is_set())
 
4709
    {
 
4710
      Alter_info tmp_alter_info(*alter_info, session->mem_root);
 
4711
 
 
4712
      /*
 
4713
        If no table rename,
 
4714
        check if table can be altered on-line
 
4715
      */
 
4716
      if (!(altered_table= create_altered_table(session,
 
4717
                                                table,
 
4718
                                                new_db,
 
4719
                                                create_info,
 
4720
                                                &tmp_alter_info,
 
4721
                                                !strcmp(db, new_db))))
 
4722
        goto err;
 
4723
 
 
4724
      switch (table->file->check_if_supported_alter(altered_table,
 
4725
                                                    create_info,
 
4726
                                                    &ha_alter_flags,
 
4727
                                                    table_changes)) {
 
4728
      case HA_ALTER_SUPPORTED_WAIT_LOCK:
 
4729
      case HA_ALTER_SUPPORTED_NO_LOCK:
 
4730
        /*
 
4731
          @todo: Currently we always acquire an exclusive name
 
4732
          lock on the table metadata when performing fast or online
 
4733
          ALTER Table. In future we may consider this unnecessary,
 
4734
          and narrow the scope of the exclusive name lock to only
 
4735
          cover manipulation with .frms. Storage engine API
 
4736
          call check_if_supported_alter has provision for this
 
4737
          already now.
 
4738
        */
 
4739
        need_copy_table= false;
 
4740
        break;
 
4741
      case HA_ALTER_NOT_SUPPORTED:
 
4742
        if (alter_info->build_method == HA_BUILD_ONLINE)
 
4743
        {
 
4744
          my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
4745
          close_temporary_table(session, altered_table, 1, 1);
 
4746
          goto err;
 
4747
        }
 
4748
        need_copy_table= true;
 
4749
        break;
 
4750
      case HA_ALTER_ERROR:
 
4751
      default:
 
4752
        close_temporary_table(session, altered_table, 1, 1);
 
4753
        goto err;
 
4754
      }
 
4755
 
 
4756
    }
 
4757
    /* TODO need to check if changes can be handled as fast ALTER Table */
 
4758
    if (!altered_table)
 
4759
      need_copy_table= true;
 
4760
 
 
4761
    if (!need_copy_table)
 
4762
    {
 
4763
      error= mysql_fast_or_online_alter_table(session,
 
4764
                                              table,
 
4765
                                              altered_table,
 
4766
                                              create_info,
 
4767
                                              &ha_alter_info,
 
4768
                                              &ha_alter_flags,
 
4769
                                              alter_info->keys_onoff);
 
4770
      if (session->lock)
 
4771
      {
 
4772
        mysql_unlock_tables(session, session->lock);
 
4773
        session->lock=0;
 
4774
      }
 
4775
      close_temporary_table(session, altered_table, 1, 1);
 
4776
 
 
4777
      if (error)
 
4778
      {
 
4779
        switch (error) {
 
4780
        case(-1):
 
4781
          goto err_with_placeholders;
 
4782
        default:
 
4783
          goto err;
 
4784
        }
 
4785
      }
 
4786
      else
 
4787
      {
 
4788
        pthread_mutex_lock(&LOCK_open);
 
4789
        goto end_online;
 
4790
      }
 
4791
    }
 
4792
 
 
4793
    if (altered_table)
 
4794
      close_temporary_table(session, altered_table, 1, 1);
 
4795
  }
 
4796
 
 
4797
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX,
 
4798
           (unsigned long)current_pid, session->thread_id);
 
4799
  /* Safety fix for innodb */
 
4800
  if (lower_case_table_names)
 
4801
    my_casedn_str(files_charset_info, tmp_name);
 
4802
 
 
4803
 
 
4804
  /* Create a temporary table with the new format */
 
4805
  if ((error= create_temporary_table(session, table, new_db, tmp_name,
 
4806
                                     create_info, alter_info,
 
4807
                                     !strcmp(db, new_db))))
 
4808
  {
 
4809
    goto err;
 
4810
  }
 
4811
 
 
4812
  /* Open the table so we need to copy the data to it. */
 
4813
  if (table->s->tmp_table)
 
4814
  {
 
4815
    TableList tbl;
 
4816
    memset(&tbl, 0, sizeof(tbl));
 
4817
    tbl.db= new_db;
 
4818
    tbl.table_name= tbl.alias= tmp_name;
 
4819
    /* Table is in session->temporary_tables */
 
4820
    new_table= open_table(session, &tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
 
4821
  }
 
4822
  else
 
4823
  {
 
4824
    char tmp_path[FN_REFLEN];
 
4825
    /* table is a normal table: Create temporary table in same directory */
 
4826
    build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, "",
 
4827
                         FN_IS_TMP);
 
4828
    /* Open our intermediate table */
 
4829
    new_table=open_temporary_table(session, tmp_path, new_db, tmp_name, 0, OTM_OPEN);
 
4830
  }
 
4831
  if (!new_table)
 
4832
    goto err1;
 
4833
 
 
4834
  /* Copy the data if necessary. */
 
4835
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
 
4836
  session->cuted_fields=0L;
 
4837
  session->set_proc_info("copy to tmp table");
 
4838
  copied=deleted=0;
 
4839
  /*
 
4840
    We do not copy data for MERGE tables. Only the children have data.
 
4841
    MERGE tables have HA_NO_COPY_ON_ALTER set.
 
4842
  */
 
4843
  if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
 
4844
  {
 
4845
    /* We don't want update TIMESTAMP fields during ALTER Table. */
 
4846
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
4847
    new_table->next_number_field=new_table->found_next_number_field;
 
4848
    error= copy_data_between_tables(table, new_table,
 
4849
                                    alter_info->create_list, ignore,
 
4850
                                   order_num, order, &copied, &deleted,
 
4851
                                    alter_info->keys_onoff,
 
4852
                                    alter_info->error_if_not_empty);
 
4853
  }
 
4854
  else
 
4855
  {
 
4856
    pthread_mutex_lock(&LOCK_open);
 
4857
    wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
4858
    pthread_mutex_unlock(&LOCK_open);
 
4859
    alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
4860
                            alter_info->keys_onoff);
 
4861
    error= ha_autocommit_or_rollback(session, 0);
 
4862
    if (end_active_trans(session))
 
4863
      error= 1;
 
4864
  }
 
4865
  /* We must not ignore bad input! */;
 
4866
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
4867
 
 
4868
  if (table->s->tmp_table != NO_TMP_TABLE)
 
4869
  {
 
4870
    /* We changed a temporary table */
 
4871
    if (error)
 
4872
      goto err1;
 
4873
    /* Close lock if this is a transactional table */
 
4874
    if (session->lock)
 
4875
    {
 
4876
      mysql_unlock_tables(session, session->lock);
 
4877
      session->lock=0;
 
4878
    }
 
4879
    /* Remove link to old table and rename the new one */
 
4880
    close_temporary_table(session, table, 1, 1);
 
4881
    /* Should pass the 'new_name' as we store table name in the cache */
 
4882
    if (rename_temporary_table(session, new_table, new_db, new_name))
 
4883
      goto err1;
 
4884
    goto end_temporary;
 
4885
  }
 
4886
 
 
4887
  if (new_table)
 
4888
  {
 
4889
    /*
 
4890
      Close the intermediate table that will be the new table.
 
4891
      Note that MERGE tables do not have their children attached here.
 
4892
    */
 
4893
    intern_close_table(new_table);
 
4894
    free(new_table);
 
4895
  }
 
4896
  pthread_mutex_lock(&LOCK_open);
 
4897
  if (error)
 
4898
  {
 
4899
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
4900
    pthread_mutex_unlock(&LOCK_open);
 
4901
    goto err;
 
4902
  }
 
4903
 
 
4904
  /*
 
4905
    Data is copied. Now we:
 
4906
    1) Wait until all other threads close old version of table.
 
4907
    2) Close instances of table open by this thread and replace them
 
4908
       with exclusive name-locks.
 
4909
    3) Rename the old table to a temp name, rename the new one to the
 
4910
       old name.
 
4911
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
4912
       we reopen new version of table.
 
4913
    5) Write statement to the binary log.
 
4914
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
4915
       remove name-locks from list of open tables and table cache.
 
4916
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
4917
       call to remove name-locks from table cache and list of open table.
 
4918
  */
 
4919
 
 
4920
  session->set_proc_info("rename result table");
 
4921
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX,
 
4922
           (unsigned long)current_pid, session->thread_id);
 
4923
  if (lower_case_table_names)
 
4924
    my_casedn_str(files_charset_info, old_name);
 
4925
 
 
4926
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
4927
  close_data_files_and_morph_locks(session, db, table_name);
 
4928
 
 
4929
  error=0;
 
4930
  save_old_db_type= old_db_type;
 
4931
 
 
4932
  /*
 
4933
    This leads to the storage engine (SE) not being notified for renames in
 
4934
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
4935
    more. If we have an intermediate table, then we notify the SE that
 
4936
    it should become the actual table. Later, we will recycle the old table.
 
4937
    However, in case of ALTER Table RENAME there might be no intermediate
 
4938
    table. This is when the old and new tables are compatible, according to
 
4939
    compare_table(). Then, we need one additional call to
 
4940
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
4941
    actual rename in the SE and the FRM is not touched. Note that, if the
 
4942
    table is renamed and the SE is also changed, then an intermediate table
 
4943
    is created and the additional call will not take place.
 
4944
  */
 
4945
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
 
4946
                         FN_TO_IS_TMP))
 
4947
  {
 
4948
    error=1;
 
4949
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
4950
  }
 
4951
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
 
4952
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
 
4953
  {
 
4954
    /* Try to get everything back. */
 
4955
    error=1;
 
4956
    quick_rm_table(new_db_type,new_db,new_alias, 0);
 
4957
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
4958
    mysql_rename_table(old_db_type, db, old_name, db, alias,
 
4959
                       FN_FROM_IS_TMP);
 
4960
  }
 
4961
 
 
4962
  if (error)
 
4963
  {
 
4964
    /* This shouldn't happen. But let us play it safe. */
 
4965
    goto err_with_placeholders;
 
4966
  }
 
4967
 
 
4968
  quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
 
4969
 
 
4970
end_online:
 
4971
  if (session->locked_tables && new_name == table_name && new_db == db)
 
4972
  {
 
4973
    session->in_lock_tables= 1;
 
4974
    error= reopen_tables(session, 1, 1);
 
4975
    session->in_lock_tables= 0;
 
4976
    if (error)
 
4977
      goto err_with_placeholders;
 
4978
  }
 
4979
  pthread_mutex_unlock(&LOCK_open);
 
4980
 
 
4981
  session->set_proc_info("end");
 
4982
 
 
4983
  write_bin_log(session, true, session->query, session->query_length);
 
4984
 
 
4985
  if (ha_check_storage_engine_flag(old_db_type, HTON_BIT_FLUSH_AFTER_RENAME))
 
4986
  {
 
4987
    /*
 
4988
      For the alter table to be properly flushed to the logs, we
 
4989
      have to open the new table.  If not, we get a problem on server
 
4990
      shutdown. But we do not need to attach MERGE children.
 
4991
    */
 
4992
    char table_path[FN_REFLEN];
 
4993
    Table *t_table;
 
4994
    build_table_filename(table_path, sizeof(table_path), new_db, table_name, "", 0);
 
4995
    t_table= open_temporary_table(session, table_path, new_db, tmp_name, false, OTM_OPEN);
 
4996
    if (t_table)
 
4997
    {
 
4998
      intern_close_table(t_table);
 
4999
      free(t_table);
 
5000
    }
 
5001
    else
 
5002
      errmsg_printf(ERRMSG_LVL_WARN,
 
5003
                    _("Could not open table %s.%s after rename\n"),
 
5004
                    new_db,table_name);
 
5005
    ha_flush_logs(old_db_type);
 
5006
  }
 
5007
  table_list->table=0;                          // For query cache
 
5008
 
 
5009
  if (session->locked_tables && (new_name != table_name || new_db != db))
 
5010
  {
 
5011
    /*
 
5012
      If are we under LOCK TABLES and did ALTER Table with RENAME we need
 
5013
      to remove placeholders for the old table and for the target table
 
5014
      from the list of open tables and table cache. If we are not under
 
5015
      LOCK TABLES we can rely on close_thread_tables() doing this job.
 
5016
    */
 
5017
    pthread_mutex_lock(&LOCK_open);
 
5018
    unlink_open_table(session, table, false);
 
5019
    unlink_open_table(session, name_lock, false);
 
5020
    pthread_mutex_unlock(&LOCK_open);
 
5021
  }
 
5022
 
 
5023
end_temporary:
 
5024
  /*
 
5025
   * Field::store() may have called my_error().  If this is 
 
5026
   * the case, we must not send an ok packet, since 
 
5027
   * Diagnostics_area::is_set() will fail an assert.
 
5028
   */
 
5029
  if (! session->is_error())
 
5030
  {
 
5031
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
5032
            (ulong) (copied + deleted), (ulong) deleted,
 
5033
            (ulong) session->cuted_fields);
 
5034
    session->my_ok(copied + deleted, 0L, tmp_name);
 
5035
    session->some_tables_deleted=0;
 
5036
    return false;
 
5037
  }
 
5038
  else
 
5039
  {
 
5040
    /* my_error() was called.  Return true (which means error...) */
 
5041
    return true;
 
5042
  }
 
5043
 
 
5044
err1:
 
5045
  if (new_table)
 
5046
  {
 
5047
    /* close_temporary_table() frees the new_table pointer. */
 
5048
    close_temporary_table(session, new_table, 1, 1);
 
5049
  }
 
5050
  else
 
5051
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
5052
 
 
5053
err:
 
5054
  /*
 
5055
    No default value was provided for a DATE/DATETIME field, the
 
5056
    current sql_mode doesn't allow the '0000-00-00' value and
 
5057
    the table to be altered isn't empty.
 
5058
    Report error here.
 
5059
  */
 
5060
  if (alter_info->error_if_not_empty && session->row_count)
 
5061
  {
 
5062
    const char *f_val= 0;
 
5063
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
5064
    switch (alter_info->datetime_field->sql_type)
 
5065
    {
 
5066
      case DRIZZLE_TYPE_DATE:
 
5067
        f_val= "0000-00-00";
 
5068
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
5069
        break;
 
5070
      case DRIZZLE_TYPE_DATETIME:
 
5071
        f_val= "0000-00-00 00:00:00";
 
5072
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
5073
        break;
 
5074
      default:
 
5075
        /* Shouldn't get here. */
 
5076
        assert(0);
 
5077
    }
 
5078
    bool save_abort_on_warning= session->abort_on_warning;
 
5079
    session->abort_on_warning= true;
 
5080
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5081
                                 f_val, strlength(f_val), t_type,
 
5082
                                 alter_info->datetime_field->field_name);
 
5083
    session->abort_on_warning= save_abort_on_warning;
 
5084
  }
 
5085
  if (name_lock)
 
5086
  {
 
5087
    pthread_mutex_lock(&LOCK_open);
 
5088
    unlink_open_table(session, name_lock, false);
 
5089
    pthread_mutex_unlock(&LOCK_open);
 
5090
  }
 
5091
  return(true);
 
5092
 
 
5093
err_with_placeholders:
 
5094
  /*
 
5095
    An error happened while we were holding exclusive name-lock on table
 
5096
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
5097
    from list of open tables list and table cache.
 
5098
  */
 
5099
  unlink_open_table(session, table, false);
 
5100
  if (name_lock)
 
5101
    unlink_open_table(session, name_lock, false);
 
5102
  pthread_mutex_unlock(&LOCK_open);
 
5103
  return(true);
 
5104
}
 
5105
/* mysql_alter_table */
 
5106
 
 
5107
static int
 
5108
copy_data_between_tables(Table *from,Table *to,
 
5109
                         List<Create_field> &create,
 
5110
                         bool ignore,
 
5111
                         uint32_t order_num, order_st *order,
 
5112
                         ha_rows *copied,
 
5113
                         ha_rows *deleted,
 
5114
                         enum enum_enable_or_disable keys_onoff,
 
5115
                         bool error_if_not_empty)
 
5116
{
 
5117
  int error;
 
5118
  Copy_field *copy,*copy_end;
 
5119
  ulong found_count,delete_count;
 
5120
  Session *session= current_session;
 
5121
  uint32_t length= 0;
 
5122
  SORT_FIELD *sortorder;
 
5123
  READ_RECORD info;
 
5124
  TableList   tables;
 
5125
  List<Item>   fields;
 
5126
  List<Item>   all_fields;
 
5127
  ha_rows examined_rows;
 
5128
  bool auto_increment_field_copied= 0;
 
5129
  ulong save_sql_mode;
 
5130
  uint64_t prev_insert_id;
 
5131
 
 
5132
  /*
 
5133
    Turn off recovery logging since rollback of an alter table is to
 
5134
    delete the new table so there is no need to log the changes to it.
 
5135
 
 
5136
    This needs to be done before external_lock
 
5137
  */
 
5138
  error= ha_enable_transaction(session, false);
 
5139
  if (error)
 
5140
    return(-1);
 
5141
 
 
5142
  if (!(copy= new Copy_field[to->s->fields]))
 
5143
    return(-1);                         /* purecov: inspected */
 
5144
 
 
5145
  if (to->file->ha_external_lock(session, F_WRLCK))
 
5146
    return(-1);
 
5147
 
 
5148
  /* We need external lock before we can disable/enable keys */
 
5149
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
5150
 
 
5151
  /* We can abort alter table for any table type */
 
5152
  session->abort_on_warning= !ignore;
 
5153
 
 
5154
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
5155
  to->file->ha_start_bulk_insert(from->file->stats.records);
 
5156
 
 
5157
  save_sql_mode= session->variables.sql_mode;
 
5158
 
 
5159
  List_iterator<Create_field> it(create);
 
5160
  Create_field *def;
 
5161
  copy_end=copy;
 
5162
  for (Field **ptr=to->field ; *ptr ; ptr++)
 
5163
  {
 
5164
    def=it++;
 
5165
    if (def->field)
 
5166
    {
 
5167
      if (*ptr == to->next_number_field)
 
5168
        auto_increment_field_copied= true;
 
5169
 
 
5170
      (copy_end++)->set(*ptr,def->field,0);
 
5171
    }
 
5172
 
 
5173
  }
 
5174
 
 
5175
  found_count=delete_count=0;
 
5176
 
 
5177
  if (order)
 
5178
  {
 
5179
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
 
5180
    {
 
5181
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
5182
      snprintf(warn_buff, sizeof(warn_buff),
 
5183
               _("order_st BY ignored because there is a user-defined clustered "
 
5184
                 "index in the table '%-.192s'"),
 
5185
               from->s->table_name.str);
 
5186
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
5187
                   warn_buff);
 
5188
    }
 
5189
    else
 
5190
    {
 
5191
      from->sort.io_cache= new IO_CACHE;
 
5192
      memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
 
5193
 
 
5194
      memset(&tables, 0, sizeof(tables));
 
5195
      tables.table= from;
 
5196
      tables.alias= tables.table_name= from->s->table_name.str;
 
5197
      tables.db= from->s->db.str;
 
5198
      error= 1;
 
5199
 
 
5200
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
5201
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
5202
                      &tables, fields, all_fields, order) ||
 
5203
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
5204
          (from->sort.found_records= filesort(session, from, sortorder, length,
 
5205
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
5206
                                              1, &examined_rows)) ==
 
5207
          HA_POS_ERROR)
 
5208
        goto err;
 
5209
    }
 
5210
  };
 
5211
 
 
5212
  /* Tell handler that we have values for all columns in the to table */
 
5213
  to->use_all_columns();
 
5214
  init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
 
5215
  if (ignore)
 
5216
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
5217
  session->row_count= 0;
 
5218
  restore_record(to, s->default_values);        // Create empty record
 
5219
  while (!(error=info.read_record(&info)))
 
5220
  {
 
5221
    if (session->killed)
 
5222
    {
 
5223
      session->send_kill_message();
 
5224
      error= 1;
 
5225
      break;
 
5226
    }
 
5227
    session->row_count++;
 
5228
    /* Return error if source table isn't empty. */
 
5229
    if (error_if_not_empty)
 
5230
    {
 
5231
      error= 1;
 
5232
      break;
 
5233
    }
 
5234
    if (to->next_number_field)
 
5235
    {
 
5236
      if (auto_increment_field_copied)
 
5237
        to->auto_increment_field_not_null= true;
 
5238
      else
 
5239
        to->next_number_field->reset();
 
5240
    }
 
5241
 
 
5242
    for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
5243
    {
 
5244
      copy_ptr->do_copy(copy_ptr);
 
5245
    }
 
5246
    prev_insert_id= to->file->next_insert_id;
 
5247
    update_virtual_fields_marked_for_write(to, false);
 
5248
    error=to->file->ha_write_row(to->record[0]);
 
5249
    to->auto_increment_field_not_null= false;
 
5250
    if (error)
 
5251
    {
 
5252
      if (!ignore ||
 
5253
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
5254
      {
 
5255
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
5256
         {
 
5257
           uint32_t key_nr= to->file->get_dup_key(error);
 
5258
           if ((int) key_nr >= 0)
 
5259
           {
 
5260
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
5261
             if (key_nr == 0 &&
 
5262
                 (to->key_info[0].key_part[0].field->flags &
 
5263
                  AUTO_INCREMENT_FLAG))
 
5264
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
5265
             to->file->print_keydup_error(key_nr, err_msg);
 
5266
             break;
 
5267
           }
 
5268
         }
 
5269
 
 
5270
        to->file->print_error(error,MYF(0));
 
5271
        break;
 
5272
      }
 
5273
      to->file->restore_auto_increment(prev_insert_id);
 
5274
      delete_count++;
 
5275
    }
 
5276
    else
 
5277
      found_count++;
 
5278
  }
 
5279
  end_read_record(&info);
 
5280
  free_io_cache(from);
 
5281
  delete [] copy;                               // This is never 0
 
5282
 
 
5283
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
5284
  {
 
5285
    to->file->print_error(my_errno,MYF(0));
 
5286
    error=1;
 
5287
  }
 
5288
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
5289
 
 
5290
  if (ha_enable_transaction(session, true))
 
5291
  {
 
5292
    error= 1;
 
5293
    goto err;
 
5294
  }
 
5295
 
 
5296
  /*
 
5297
    Ensure that the new table is saved properly to disk so that we
 
5298
    can do a rename
 
5299
  */
 
5300
  if (ha_autocommit_or_rollback(session, 0))
 
5301
    error=1;
 
5302
  if (end_active_trans(session))
 
5303
    error=1;
 
5304
 
 
5305
 err:
 
5306
  session->variables.sql_mode= save_sql_mode;
 
5307
  session->abort_on_warning= 0;
 
5308
  free_io_cache(from);
 
5309
  *copied= found_count;
 
5310
  *deleted=delete_count;
 
5311
  to->file->ha_release_auto_increment();
 
5312
  if (to->file->ha_external_lock(session,F_UNLCK))
 
5313
    error=1;
 
5314
  return(error > 0 ? -1 : 0);
 
5315
}
 
5316
 
 
5317
 
 
5318
/*
 
5319
  Recreates tables by calling mysql_alter_table().
 
5320
 
 
5321
  SYNOPSIS
 
5322
    mysql_recreate_table()
 
5323
    session                     Thread handler
 
5324
    tables              Tables to recreate
 
5325
 
 
5326
 RETURN
 
5327
    Like mysql_alter_table().
 
5328
*/
 
5329
bool mysql_recreate_table(Session *session, TableList *table_list)
 
5330
{
 
5331
  HA_CREATE_INFO create_info;
 
5332
  Alter_info alter_info;
 
5333
 
 
5334
  assert(!table_list->next_global);
 
5335
  /*
 
5336
    table_list->table has been closed and freed. Do not reference
 
5337
    uninitialized data. open_tables() could fail.
 
5338
  */
 
5339
  table_list->table= NULL;
 
5340
 
 
5341
  memset(&create_info, 0, sizeof(create_info));
 
5342
  create_info.row_type=ROW_TYPE_NOT_USED;
 
5343
  create_info.default_table_charset=default_charset_info;
 
5344
  /* Force alter table to recreate table */
 
5345
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
5346
  return(mysql_alter_table(session, NULL, NULL, &create_info,
 
5347
                                table_list, &alter_info, 0,
 
5348
                                (order_st *) 0, 0));
2268
5349
}
2269
5350
 
2270
5351
 
2271
5352
bool mysql_checksum_table(Session *session, TableList *tables,
2272
 
                          HA_CHECK_OPT *)
 
5353
                          HA_CHECK_OPT *check_opt)
2273
5354
{
2274
5355
  TableList *table;
2275
5356
  List<Item> field_list;
2276
5357
  Item *item;
 
5358
  Protocol *protocol= session->protocol;
2277
5359
 
2278
5360
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2279
5361
  item->maybe_null= 1;
2280
5362
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2281
5363
                                          MY_INT64_NUM_DECIMAL_DIGITS));
2282
5364
  item->maybe_null= 1;
2283
 
  if (session->client->sendFields(&field_list))
2284
 
    return true;
 
5365
  if (protocol->send_fields(&field_list,
 
5366
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
5367
    return(true);
2285
5368
 
2286
5369
  /* Open one table after the other to keep lock time as short as possible. */
2287
5370
  for (table= tables; table; table= table->next_local)
2289
5372
    char table_name[NAME_LEN*2+2];
2290
5373
    Table *t;
2291
5374
 
2292
 
    snprintf(table_name, sizeof(table_name), "%s.%s",table->db,table->table_name);
 
5375
    sprintf(table_name,"%s.%s",table->db,table->table_name);
2293
5376
 
2294
 
    t= table->table= session->openTableLock(table, TL_READ);
 
5377
    t= table->table= open_n_lock_single_table(session, table, TL_READ);
2295
5378
    session->clear_error();                     // these errors shouldn't get client
2296
5379
 
2297
 
    session->client->store(table_name);
 
5380
    protocol->prepare_for_resend();
 
5381
    protocol->store(table_name, system_charset_info);
2298
5382
 
2299
5383
    if (!t)
2300
5384
    {
2301
5385
      /* Table didn't exist */
2302
 
      session->client->store();
 
5386
      protocol->store_null();
2303
5387
      session->clear_error();
2304
5388
    }
2305
5389
    else
2306
5390
    {
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
 
      }
 
5391
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
5392
          !(check_opt->flags & T_EXTEND))
 
5393
        protocol->store((uint64_t)t->file->checksum());
 
5394
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
5395
               (check_opt->flags & T_QUICK))
 
5396
        protocol->store_null();
2314
5397
      else
2315
5398
      {
2316
5399
        /* calculating table's checksum */
2317
 
        internal::ha_checksum crc= 0;
 
5400
        ha_checksum crc= 0;
2318
5401
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
2319
5402
 
2320
5403
        t->use_all_columns();
2321
5404
 
2322
 
        if (t->cursor->ha_rnd_init(1))
2323
 
          session->client->store();
 
5405
        if (t->file->ha_rnd_init(1))
 
5406
          protocol->store_null();
2324
5407
        else
2325
5408
        {
2326
5409
          for (;;)
2327
5410
          {
2328
 
            internal::ha_checksum row_crc= 0;
2329
 
            int error= t->cursor->rnd_next(t->record[0]);
 
5411
            ha_checksum row_crc= 0;
 
5412
            int error= t->file->rnd_next(t->record[0]);
2330
5413
            if (unlikely(error))
2331
5414
            {
2332
5415
              if (error == HA_ERR_RECORD_DELETED)
2340
5423
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2341
5424
                t->record[0][0] |= 1;
2342
5425
 
2343
 
              row_crc= internal::my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
5426
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2344
5427
            }
2345
5428
 
2346
5429
            for (uint32_t i= 0; i < t->s->fields; i++ )
2351
5434
              {
2352
5435
                String tmp;
2353
5436
                f->val_str(&tmp);
2354
 
                row_crc= internal::my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
5437
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2355
5438
              }
2356
5439
              else
2357
 
                row_crc= internal::my_checksum(row_crc, f->ptr,
 
5440
                row_crc= my_checksum(row_crc, f->ptr,
2358
5441
                                     f->pack_length());
2359
5442
            }
2360
5443
 
2361
5444
            crc+= row_crc;
2362
5445
          }
2363
 
          session->client->store((uint64_t)crc);
2364
 
          t->cursor->ha_rnd_end();
 
5446
          protocol->store((uint64_t)crc);
 
5447
          t->file->ha_rnd_end();
2365
5448
        }
2366
5449
      }
2367
5450
      session->clear_error();
2368
 
      session->close_thread_tables();
 
5451
      close_thread_tables(session);
2369
5452
      table->table=0;                           // For query cache
2370
5453
    }
2371
 
    if (session->client->flush())
 
5454
    if (protocol->write())
2372
5455
      goto err;
2373
5456
  }
2374
5457
 
2376
5459
  return(false);
2377
5460
 
2378
5461
 err:
2379
 
  session->close_thread_tables();                       // Shouldn't be needed
 
5462
  close_thread_tables(session);                 // Shouldn't be needed
2380
5463
  if (table)
2381
5464
    table->table=0;
2382
5465
  return(true);
2383
5466
}
2384
5467
 
2385
 
} /* namespace drizzled */
 
5468
static bool check_engine(Session *session, const char *table_name,
 
5469
                         HA_CREATE_INFO *create_info)
 
5470
{
 
5471
  handlerton **new_engine= &create_info->db_type;
 
5472
  handlerton *req_engine= *new_engine;
 
5473
  bool no_substitution= 1;
 
5474
  if (!(*new_engine= ha_checktype(session, ha_legacy_type(req_engine),
 
5475
                                  no_substitution, 1)))
 
5476
    return true;
 
5477
 
 
5478
  if (req_engine && req_engine != *new_engine)
 
5479
  {
 
5480
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
5481
                       ER_WARN_USING_OTHER_HANDLER,
 
5482
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
5483
                       ha_resolve_storage_engine_name(*new_engine),
 
5484
                       table_name);
 
5485
  }
 
5486
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
5487
      ha_check_storage_engine_flag(*new_engine, HTON_BIT_TEMPORARY_NOT_SUPPORTED))
 
5488
  {
 
5489
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
5490
    {
 
5491
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
5492
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
 
5493
      *new_engine= 0;
 
5494
      return true;
 
5495
    }
 
5496
    *new_engine= myisam_hton;
 
5497
  }
 
5498
  return false;
 
5499
}