~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_table.cc

  • Committer: Brian Aker
  • Date: 2008-07-08 16:17:31 UTC
  • Revision ID: brian@tangent.org-20080708161731-io36j7igglok79py
DATE cleanup.

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>
20
 
#include <drizzled/show.h>
21
 
#include <drizzled/error.h>
22
 
#include <drizzled/gettext.h>
23
 
#include <drizzled/data_home.h>
24
 
#include <drizzled/sql_parse.h>
25
 
#include <drizzled/my_hash.h>
26
 
#include <drizzled/sql_lex.h>
27
 
#include <drizzled/session.h>
28
 
#include <drizzled/sql_base.h>
29
 
#include "drizzled/strfunc.h"
30
 
#include <drizzled/db.h>
31
 
#include <drizzled/lock.h>
32
 
#include <drizzled/unireg.h>
33
 
#include <drizzled/item/int.h>
34
 
#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/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>
51
 
 
52
 
#include <boost/unordered_set.hpp>
53
 
 
54
 
using namespace std;
55
 
 
56
 
namespace drizzled
57
 
{
58
 
 
59
 
extern pid_t current_pid;
60
 
 
61
 
bool is_primary_key(KeyInfo *key_info)
62
 
{
63
 
  static const char * primary_key_name="PRIMARY";
64
 
  return (strcmp(key_info->name, primary_key_name)==0);
65
 
}
66
 
 
67
 
const char* is_primary_key_name(const char* key_name)
68
 
{
69
 
  static const char * primary_key_name="PRIMARY";
70
 
  if (strcmp(key_name, primary_key_name)==0)
71
 
    return key_name;
72
 
  else
73
 
    return NULL;
74
 
}
75
 
 
76
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
77
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
78
 
 
79
 
static bool prepare_blob_field(Session *session, CreateField *sql_field);
80
 
 
81
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
82
 
{
83
 
  /*
84
 
    If the table character set was not given explicitly,
85
 
    let's fetch the database default character set and
86
 
    apply it to the table.
87
 
  */
88
 
  SchemaIdentifier identifier(db);
89
 
  if (create_info->default_table_charset == NULL)
90
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
91
 
}
 
18
#include "mysql_priv.h"
 
19
#include <hash.h>
 
20
#include <myisam.h>
 
21
#include <my_dir.h>
 
22
#include "sql_show.h"
 
23
 
 
24
int creating_table= 0;        // How many mysql_create_table are running
 
25
 
 
26
const char *primary_key_name="PRIMARY";
 
27
 
 
28
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
29
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
 
30
static int copy_data_between_tables(TABLE *from,TABLE *to,
 
31
                                    List<Create_field> &create, bool ignore,
 
32
                                    uint order_num, ORDER *order,
 
33
                                    ha_rows *copied,ha_rows *deleted,
 
34
                                    enum enum_enable_or_disable keys_onoff,
 
35
                                    bool error_if_not_empty);
 
36
 
 
37
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
 
38
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
 
39
static int
 
40
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 
41
                           Alter_info *alter_info,
 
42
                           bool tmp_table,
 
43
                               uint *db_options,
 
44
                               handler *file, KEY **key_info_buffer,
 
45
                               uint *key_count, int select_field_count);
 
46
static bool
 
47
mysql_prepare_alter_table(THD *thd, TABLE *table,
 
48
                          HA_CREATE_INFO *create_info,
 
49
                          Alter_info *alter_info);
 
50
 
 
51
#ifndef DBUG_OFF
 
52
 
 
53
/* Wait until we get a 'mysql_kill' signal */
 
54
 
 
55
static void wait_for_kill_signal(THD *thd)
 
56
{
 
57
  while (thd->killed == 0)
 
58
    sleep(1);
 
59
  // Reset signal and continue as if nothing happend
 
60
  thd->killed= THD::NOT_KILLED;
 
61
}
 
62
#endif
 
63
 
 
64
 
 
65
/*
 
66
  Translate a file name to a table name (WL #1324).
 
67
 
 
68
  SYNOPSIS
 
69
    filename_to_tablename()
 
70
      from                      The file name in my_charset_filename.
 
71
      to                OUT     The table name in system_charset_info.
 
72
      to_length                 The size of the table name buffer.
 
73
 
 
74
  RETURN
 
75
    Table name length.
 
76
*/
 
77
 
 
78
uint filename_to_tablename(const char *from, char *to, uint to_length)
 
79
{
 
80
  uint errors;
 
81
  uint res;
 
82
  DBUG_ENTER("filename_to_tablename");
 
83
  DBUG_PRINT("enter", ("from '%s'", from));
 
84
 
 
85
  if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
 
86
  {
 
87
    /* Temporary table name. */
 
88
    res= (strnmov(to, from, to_length) - to);
 
89
  }
 
90
  else
 
91
  {
 
92
    res= strconvert(&my_charset_filename, from,
 
93
                    system_charset_info,  to, to_length, &errors);
 
94
    if (errors) // Old 5.0 name
 
95
    {
 
96
      res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX,  from, NullS) -
 
97
            to);
 
98
      sql_print_error("Invalid (old?) table or database name '%s'", from);
 
99
      /*
 
100
        TODO: add a stored procedure for fix table and database names,
 
101
        and mention its name in error log.
 
102
      */
 
103
    }
 
104
  }
 
105
 
 
106
  DBUG_PRINT("exit", ("to '%s'", to));
 
107
  DBUG_RETURN(res);
 
108
}
 
109
 
 
110
 
 
111
/*
 
112
  Translate a table name to a file name (WL #1324).
 
113
 
 
114
  SYNOPSIS
 
115
    tablename_to_filename()
 
116
      from                      The table name in system_charset_info.
 
117
      to                OUT     The file name in my_charset_filename.
 
118
      to_length                 The size of the file name buffer.
 
119
 
 
120
  RETURN
 
121
    File name length.
 
122
*/
 
123
 
 
124
uint tablename_to_filename(const char *from, char *to, uint to_length)
 
125
{
 
126
  uint errors, length;
 
127
  DBUG_ENTER("tablename_to_filename");
 
128
  DBUG_PRINT("enter", ("from '%s'", from));
 
129
 
 
130
  if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
 
131
                                 MYSQL50_TABLE_NAME_PREFIX_LENGTH))
 
132
    DBUG_RETURN((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
 
133
                                to_length-1) -
 
134
                        (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
 
135
  length= strconvert(system_charset_info, from,
 
136
                     &my_charset_filename, to, to_length, &errors);
 
137
  if (check_if_legal_tablename(to) &&
 
138
      length + 4 < to_length)
 
139
  {
 
140
    memcpy(to + length, "@@@", 4);
 
141
    length+= 3;
 
142
  }
 
143
  DBUG_PRINT("exit", ("to '%s'", to));
 
144
  DBUG_RETURN(length);
 
145
}
 
146
 
 
147
 
 
148
/*
 
149
  Creates path to a file: mysql_data_dir/db/table.ext
 
150
 
 
151
  SYNOPSIS
 
152
   build_table_filename()
 
153
     buff                       Where to write result in my_charset_filename.
 
154
                                This may be the same as table_name.
 
155
     bufflen                    buff size
 
156
     db                         Database name in system_charset_info.
 
157
     table_name                 Table name in system_charset_info.
 
158
     ext                        File extension.
 
159
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
160
                                table_name is temporary, do not change.
 
161
 
 
162
  NOTES
 
163
 
 
164
    Uses database and table name, and extension to create
 
165
    a file name in mysql_data_dir. Database and table
 
166
    names are converted from system_charset_info into "fscs".
 
167
    Unless flags indicate a temporary table name.
 
168
    'db' is always converted.
 
169
    'ext' is not converted.
 
170
 
 
171
    The conversion suppression is required for ALTER TABLE. This
 
172
    statement creates intermediate tables. These are regular
 
173
    (non-temporary) tables with a temporary name. Their path names must
 
174
    be derivable from the table name. So we cannot use
 
175
    build_tmptable_filename() for them.
 
176
 
 
177
  RETURN
 
178
    path length
 
179
*/
 
180
 
 
181
uint build_table_filename(char *buff, size_t bufflen, const char *db,
 
182
                          const char *table_name, const char *ext, uint flags)
 
183
{
 
184
  char dbbuff[FN_REFLEN];
 
185
  char tbbuff[FN_REFLEN];
 
186
  DBUG_ENTER("build_table_filename");
 
187
  DBUG_PRINT("enter", ("db: '%s'  table_name: '%s'  ext: '%s'  flags: %x",
 
188
                       db, table_name, ext, flags));
 
189
 
 
190
  if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
191
    strnmov(tbbuff, table_name, sizeof(tbbuff));
 
192
  else
 
193
    VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
 
194
 
 
195
  VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
 
196
 
 
197
  char *end = buff + bufflen;
 
198
  /* Don't add FN_ROOTDIR if mysql_data_home already includes it */
 
199
  char *pos = strnmov(buff, mysql_data_home, bufflen);
 
200
  int rootdir_len= strlen(FN_ROOTDIR);
 
201
  if (pos - rootdir_len >= buff &&
 
202
      memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
 
203
    pos= strnmov(pos, FN_ROOTDIR, end - pos);
 
204
  pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
 
205
#ifdef USE_SYMDIR
 
206
  unpack_dirname(buff, buff);
 
207
  pos= strend(buff);
 
208
#endif
 
209
  pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
 
210
 
 
211
  DBUG_PRINT("exit", ("buff: '%s'", buff));
 
212
  DBUG_RETURN(pos - buff);
 
213
}
 
214
 
 
215
 
 
216
/*
 
217
  Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
 
218
 
 
219
  SYNOPSIS
 
220
   build_tmptable_filename()
 
221
     thd                        The thread handle.
 
222
     buff                       Where to write result in my_charset_filename.
 
223
     bufflen                    buff size
 
224
 
 
225
  NOTES
 
226
 
 
227
    Uses current_pid, thread_id, and tmp_table counter to create
 
228
    a file name in mysql_tmpdir.
 
229
 
 
230
  RETURN
 
231
    path length
 
232
*/
 
233
 
 
234
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
 
235
{
 
236
  DBUG_ENTER("build_tmptable_filename");
 
237
 
 
238
  char *p= strnmov(buff, mysql_tmpdir, bufflen);
 
239
  snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
 
240
              tmp_file_prefix, current_pid,
 
241
              thd->thread_id, thd->tmp_table++, reg_ext);
 
242
 
 
243
  if (lower_case_table_names)
 
244
  {
 
245
    /* Convert all except tmpdir to lower case */
 
246
    my_casedn_str(files_charset_info, p);
 
247
  }
 
248
 
 
249
  uint length= unpack_filename(buff, buff);
 
250
  DBUG_PRINT("exit", ("buff: '%s'", buff));
 
251
  DBUG_RETURN(length);
 
252
}
 
253
 
 
254
/*
 
255
--------------------------------------------------------------------------
 
256
 
 
257
   MODULE: DDL log
 
258
   -----------------
 
259
 
 
260
   This module is used to ensure that we can recover from crashes that occur
 
261
   in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
 
262
   We need to ensure that both t1 and t2 are dropped and not only t1 and
 
263
   also that each table drop is entirely done and not "half-baked".
 
264
 
 
265
   To support this we create log entries for each meta-data statement in the
 
266
   ddl log while we are executing. These entries are dropped when the
 
267
   operation is completed.
 
268
 
 
269
   At recovery those entries that were not completed will be executed.
 
270
 
 
271
   There is only one ddl log in the system and it is protected by a mutex
 
272
   and there is a global struct that contains information about its current
 
273
   state.
 
274
 
 
275
   History:
 
276
   First version written in 2006 by Mikael Ronstrom
 
277
--------------------------------------------------------------------------
 
278
*/
 
279
 
 
280
 
 
281
struct st_global_ddl_log
 
282
{
 
283
  /*
 
284
    We need to adjust buffer size to be able to handle downgrades/upgrades
 
285
    where IO_SIZE has changed. We'll set the buffer size such that we can
 
286
    handle that the buffer size was upto 4 times bigger in the version
 
287
    that wrote the DDL log.
 
288
  */
 
289
  char file_entry_buf[4*IO_SIZE];
 
290
  char file_name_str[FN_REFLEN];
 
291
  char *file_name;
 
292
  DDL_LOG_MEMORY_ENTRY *first_free;
 
293
  DDL_LOG_MEMORY_ENTRY *first_used;
 
294
  uint num_entries;
 
295
  File file_id;
 
296
  uint name_len;
 
297
  uint io_size;
 
298
  bool inited;
 
299
  bool do_release;
 
300
  bool recovery_phase;
 
301
  st_global_ddl_log() : inited(false), do_release(false) {}
 
302
};
 
303
 
 
304
st_global_ddl_log global_ddl_log;
 
305
 
 
306
pthread_mutex_t LOCK_gdl;
 
307
 
 
308
#define DDL_LOG_ENTRY_TYPE_POS 0
 
309
#define DDL_LOG_ACTION_TYPE_POS 1
 
310
#define DDL_LOG_PHASE_POS 2
 
311
#define DDL_LOG_NEXT_ENTRY_POS 4
 
312
#define DDL_LOG_NAME_POS 8
 
313
 
 
314
#define DDL_LOG_NUM_ENTRY_POS 0
 
315
#define DDL_LOG_NAME_LEN_POS 4
 
316
#define DDL_LOG_IO_SIZE_POS 8
 
317
 
 
318
/*
 
319
  Read one entry from ddl log file
 
320
  SYNOPSIS
 
321
    read_ddl_log_file_entry()
 
322
    entry_no                     Entry number to read
 
323
  RETURN VALUES
 
324
    true                         Error
 
325
    false                        Success
 
326
*/
 
327
 
 
328
static bool read_ddl_log_file_entry(uint entry_no)
 
329
{
 
330
  bool error= false;
 
331
  File file_id= global_ddl_log.file_id;
 
332
  uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
 
333
  ssize_t io_size= (ssize_t)global_ddl_log.io_size;
 
334
  DBUG_ENTER("read_ddl_log_file_entry");
 
335
 
 
336
  if (pread(file_id, file_entry_buf, io_size, io_size * entry_no) != io_size)
 
337
    error= true;
 
338
  DBUG_RETURN(error);
 
339
}
 
340
 
 
341
 
 
342
/*
 
343
  Write one entry from ddl log file
 
344
  SYNOPSIS
 
345
    write_ddl_log_file_entry()
 
346
    entry_no                     Entry number to read
 
347
  RETURN VALUES
 
348
    true                         Error
 
349
    false                        Success
 
350
*/
 
351
 
 
352
static bool write_ddl_log_file_entry(uint entry_no)
 
353
{
 
354
  bool error= false;
 
355
  File file_id= global_ddl_log.file_id;
 
356
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
357
  DBUG_ENTER("write_ddl_log_file_entry");
 
358
 
 
359
  if (pwrite(file_id, (uchar*)file_entry_buf,
 
360
             IO_SIZE, IO_SIZE * entry_no) != IO_SIZE)
 
361
    error= true;
 
362
  DBUG_RETURN(error);
 
363
}
 
364
 
 
365
 
 
366
/*
 
367
  Write ddl log header
 
368
  SYNOPSIS
 
369
    write_ddl_log_header()
 
370
  RETURN VALUES
 
371
    true                      Error
 
372
    false                     Success
 
373
*/
 
374
 
 
375
static bool write_ddl_log_header()
 
376
{
 
377
  uint16 const_var;
 
378
  bool error= false;
 
379
  DBUG_ENTER("write_ddl_log_header");
 
380
 
 
381
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
 
382
            global_ddl_log.num_entries);
 
383
  const_var= FN_LEN;
 
384
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
 
385
            (ulong) const_var);
 
386
  const_var= IO_SIZE;
 
387
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
 
388
            (ulong) const_var);
 
389
  if (write_ddl_log_file_entry(0UL))
 
390
  {
 
391
    sql_print_error("Error writing ddl log header");
 
392
    DBUG_RETURN(true);
 
393
  }
 
394
  VOID(sync_ddl_log());
 
395
  DBUG_RETURN(error);
 
396
}
 
397
 
 
398
 
 
399
/*
 
400
  Create ddl log file name
 
401
  SYNOPSIS
 
402
    create_ddl_log_file_name()
 
403
    file_name                   Filename setup
 
404
  RETURN VALUES
 
405
    NONE
 
406
*/
 
407
 
 
408
static inline void create_ddl_log_file_name(char *file_name)
 
409
{
 
410
  strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
 
411
}
 
412
 
 
413
 
 
414
/*
 
415
  Read header of ddl log file
 
416
  SYNOPSIS
 
417
    read_ddl_log_header()
 
418
  RETURN VALUES
 
419
    > 0                  Last entry in ddl log
 
420
    0                    No entries in ddl log
 
421
  DESCRIPTION
 
422
    When we read the ddl log header we get information about maximum sizes
 
423
    of names in the ddl log and we also get information about the number
 
424
    of entries in the ddl log.
 
425
*/
 
426
 
 
427
static uint read_ddl_log_header()
 
428
{
 
429
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
430
  char file_name[FN_REFLEN];
 
431
  uint entry_no;
 
432
  bool successful_open= false;
 
433
  DBUG_ENTER("read_ddl_log_header");
 
434
 
 
435
  create_ddl_log_file_name(file_name);
 
436
  if ((global_ddl_log.file_id= my_open(file_name,
 
437
                                        O_RDWR | O_BINARY, MYF(0))) >= 0)
 
438
  {
 
439
    if (read_ddl_log_file_entry(0UL))
 
440
    {
 
441
      /* Write message into error log */
 
442
      sql_print_error("Failed to read ddl log file in recovery");
 
443
    }
 
444
    else
 
445
      successful_open= true;
 
446
  }
 
447
  entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
 
448
  global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
 
449
  if (successful_open)
 
450
  {
 
451
    global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
 
452
    DBUG_ASSERT(global_ddl_log.io_size <=
 
453
                sizeof(global_ddl_log.file_entry_buf));
 
454
  }
 
455
  else
 
456
  {
 
457
    entry_no= 0;
 
458
  }
 
459
  global_ddl_log.first_free= NULL;
 
460
  global_ddl_log.first_used= NULL;
 
461
  global_ddl_log.num_entries= 0;
 
462
  VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
 
463
  global_ddl_log.do_release= true;
 
464
  DBUG_RETURN(entry_no);
 
465
}
 
466
 
 
467
 
 
468
/*
 
469
  Read a ddl log entry
 
470
  SYNOPSIS
 
471
    read_ddl_log_entry()
 
472
    read_entry               Number of entry to read
 
473
    out:entry_info           Information from entry
 
474
  RETURN VALUES
 
475
    true                     Error
 
476
    false                    Success
 
477
  DESCRIPTION
 
478
    Read a specified entry in the ddl log
 
479
*/
 
480
 
 
481
bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
 
482
{
 
483
  char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
 
484
  uint inx;
 
485
  uchar single_char;
 
486
  DBUG_ENTER("read_ddl_log_entry");
 
487
 
 
488
  if (read_ddl_log_file_entry(read_entry))
 
489
  {
 
490
    DBUG_RETURN(true);
 
491
  }
 
492
  ddl_log_entry->entry_pos= read_entry;
 
493
  single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
 
494
  ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
 
495
  single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
 
496
  ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
 
497
  ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
 
498
  ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
 
499
  ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
 
500
  inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
 
501
  ddl_log_entry->from_name= &file_entry_buf[inx];
 
502
  inx+= global_ddl_log.name_len;
 
503
  ddl_log_entry->handler_name= &file_entry_buf[inx];
 
504
  DBUG_RETURN(false);
 
505
}
 
506
 
 
507
 
 
508
/*
 
509
  Initialise ddl log
 
510
  SYNOPSIS
 
511
    init_ddl_log()
 
512
 
 
513
  DESCRIPTION
 
514
    Write the header of the ddl log file and length of names. Also set
 
515
    number of entries to zero.
 
516
 
 
517
  RETURN VALUES
 
518
    true                     Error
 
519
    false                    Success
 
520
*/
 
521
 
 
522
static bool init_ddl_log()
 
523
{
 
524
  char file_name[FN_REFLEN];
 
525
  DBUG_ENTER("init_ddl_log");
 
526
 
 
527
  if (global_ddl_log.inited)
 
528
    goto end;
 
529
 
 
530
  global_ddl_log.io_size= IO_SIZE;
 
531
  create_ddl_log_file_name(file_name);
 
532
  if ((global_ddl_log.file_id= my_create(file_name,
 
533
                                         CREATE_MODE,
 
534
                                         O_RDWR | O_TRUNC | O_BINARY,
 
535
                                         MYF(MY_WME))) < 0)
 
536
  {
 
537
    /* Couldn't create ddl log file, this is serious error */
 
538
    sql_print_error("Failed to open ddl log file");
 
539
    DBUG_RETURN(true);
 
540
  }
 
541
  global_ddl_log.inited= true;
 
542
  if (write_ddl_log_header())
 
543
  {
 
544
    VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
 
545
    global_ddl_log.inited= false;
 
546
    DBUG_RETURN(true);
 
547
  }
 
548
 
 
549
end:
 
550
  DBUG_RETURN(false);
 
551
}
 
552
 
 
553
 
 
554
/*
 
555
  Execute one action in a ddl log entry
 
556
  SYNOPSIS
 
557
    execute_ddl_log_action()
 
558
    ddl_log_entry              Information in action entry to execute
 
559
  RETURN VALUES
 
560
    true                       Error
 
561
    false                      Success
 
562
*/
 
563
 
 
564
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
 
565
{
 
566
  bool frm_action= false;
 
567
  LEX_STRING handler_name;
 
568
  handler *file= NULL;
 
569
  MEM_ROOT mem_root;
 
570
  int error= true;
 
571
  char to_path[FN_REFLEN];
 
572
  char from_path[FN_REFLEN];
 
573
  handlerton *hton;
 
574
  DBUG_ENTER("execute_ddl_log_action");
 
575
 
 
576
  if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
 
577
  {
 
578
    DBUG_RETURN(false);
 
579
  }
 
580
  handler_name.str= (char*)ddl_log_entry->handler_name;
 
581
  handler_name.length= strlen(ddl_log_entry->handler_name);
 
582
  init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); 
 
583
  if (!strcmp(ddl_log_entry->handler_name, reg_ext))
 
584
    frm_action= true;
 
585
  else
 
586
  {
 
587
    plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
 
588
    if (!plugin)
 
589
    {
 
590
      my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
 
591
      goto error;
 
592
    }
 
593
    hton= plugin_data(plugin, handlerton*);
 
594
    file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
 
595
    if (!file)
 
596
    {
 
597
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
598
      goto error;
 
599
    }
 
600
  }
 
601
  switch (ddl_log_entry->action_type)
 
602
  {
 
603
    case DDL_LOG_REPLACE_ACTION:
 
604
    case DDL_LOG_DELETE_ACTION:
 
605
    {
 
606
      if (ddl_log_entry->phase == 0)
 
607
      {
 
608
        if (frm_action)
 
609
        {
 
610
          strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
 
611
          if ((error= my_delete(to_path, MYF(MY_WME))))
 
612
          {
 
613
            if (my_errno != ENOENT)
 
614
              break;
 
615
          }
 
616
        }
 
617
        else
 
618
        {
 
619
          if ((error= file->ha_delete_table(ddl_log_entry->name)))
 
620
          {
 
621
            if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
 
622
              break;
 
623
          }
 
624
        }
 
625
        if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
 
626
          break;
 
627
        VOID(sync_ddl_log());
 
628
        error= false;
 
629
        if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
 
630
          break;
 
631
      }
 
632
      DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
 
633
      /*
 
634
        Fall through and perform the rename action of the replace
 
635
        action. We have already indicated the success of the delete
 
636
        action in the log entry by stepping up the phase.
 
637
      */
 
638
    }
 
639
    case DDL_LOG_RENAME_ACTION:
 
640
    {
 
641
      error= true;
 
642
      if (frm_action)
 
643
      {
 
644
        strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
 
645
        strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
 
646
        if (my_rename(from_path, to_path, MYF(MY_WME)))
 
647
          break;
 
648
      }
 
649
      else
 
650
      {
 
651
        if (file->ha_rename_table(ddl_log_entry->from_name,
 
652
                                  ddl_log_entry->name))
 
653
          break;
 
654
      }
 
655
      if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
 
656
        break;
 
657
      VOID(sync_ddl_log());
 
658
      error= false;
 
659
      break;
 
660
    }
 
661
    default:
 
662
      DBUG_ASSERT(0);
 
663
      break;
 
664
  }
 
665
  delete file;
 
666
error:
 
667
  free_root(&mem_root, MYF(0)); 
 
668
  DBUG_RETURN(error);
 
669
}
 
670
 
 
671
 
 
672
/*
 
673
  Get a free entry in the ddl log
 
674
  SYNOPSIS
 
675
    get_free_ddl_log_entry()
 
676
    out:active_entry                A ddl log memory entry returned
 
677
  RETURN VALUES
 
678
    true                       Error
 
679
    false                      Success
 
680
*/
 
681
 
 
682
static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
 
683
                                   bool *write_header)
 
684
{
 
685
  DDL_LOG_MEMORY_ENTRY *used_entry;
 
686
  DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
 
687
  DBUG_ENTER("get_free_ddl_log_entry");
 
688
 
 
689
  if (global_ddl_log.first_free == NULL)
 
690
  {
 
691
    if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
 
692
                              sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
 
693
    {
 
694
      sql_print_error("Failed to allocate memory for ddl log free list");
 
695
      DBUG_RETURN(true);
 
696
    }
 
697
    global_ddl_log.num_entries++;
 
698
    used_entry->entry_pos= global_ddl_log.num_entries;
 
699
    *write_header= true;
 
700
  }
 
701
  else
 
702
  {
 
703
    used_entry= global_ddl_log.first_free;
 
704
    global_ddl_log.first_free= used_entry->next_log_entry;
 
705
    *write_header= false;
 
706
  }
 
707
  /*
 
708
    Move from free list to used list
 
709
  */
 
710
  used_entry->next_log_entry= first_used;
 
711
  used_entry->prev_log_entry= NULL;
 
712
  global_ddl_log.first_used= used_entry;
 
713
  if (first_used)
 
714
    first_used->prev_log_entry= used_entry;
 
715
 
 
716
  *active_entry= used_entry;
 
717
  DBUG_RETURN(false);
 
718
}
 
719
 
 
720
 
 
721
/*
 
722
  External interface methods for the DDL log Module
 
723
  ---------------------------------------------------
 
724
*/
 
725
 
 
726
/*
 
727
  SYNOPSIS
 
728
    write_ddl_log_entry()
 
729
    ddl_log_entry         Information about log entry
 
730
    out:entry_written     Entry information written into   
 
731
 
 
732
  RETURN VALUES
 
733
    true                      Error
 
734
    false                     Success
 
735
 
 
736
  DESCRIPTION
 
737
    A careful write of the ddl log is performed to ensure that we can
 
738
    handle crashes occurring during CREATE and ALTER TABLE processing.
 
739
*/
 
740
 
 
741
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
 
742
                         DDL_LOG_MEMORY_ENTRY **active_entry)
 
743
{
 
744
  bool error, write_header;
 
745
  DBUG_ENTER("write_ddl_log_entry");
 
746
 
 
747
  if (init_ddl_log())
 
748
  {
 
749
    DBUG_RETURN(true);
 
750
  }
 
751
  global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
 
752
                                    (char)DDL_LOG_ENTRY_CODE;
 
753
  global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
 
754
                                    (char)ddl_log_entry->action_type;
 
755
  global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
 
756
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
 
757
            ddl_log_entry->next_entry);
 
758
  DBUG_ASSERT(strlen(ddl_log_entry->name) < FN_LEN);
 
759
  strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
 
760
          ddl_log_entry->name, FN_LEN - 1);
 
761
  if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
 
762
      ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
 
763
  {
 
764
    DBUG_ASSERT(strlen(ddl_log_entry->from_name) < FN_LEN);
 
765
    strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
 
766
          ddl_log_entry->from_name, FN_LEN - 1);
 
767
  }
 
768
  else
 
769
    global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
 
770
  DBUG_ASSERT(strlen(ddl_log_entry->handler_name) < FN_LEN);
 
771
  strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
 
772
          ddl_log_entry->handler_name, FN_LEN - 1);
 
773
  if (get_free_ddl_log_entry(active_entry, &write_header))
 
774
  {
 
775
    DBUG_RETURN(true);
 
776
  }
 
777
  error= false;
 
778
  if (write_ddl_log_file_entry((*active_entry)->entry_pos))
 
779
  {
 
780
    error= true;
 
781
    sql_print_error("Failed to write entry_no = %u",
 
782
                    (*active_entry)->entry_pos);
 
783
  }
 
784
  if (write_header && !error)
 
785
  {
 
786
    VOID(sync_ddl_log());
 
787
    if (write_ddl_log_header())
 
788
      error= true;
 
789
  }
 
790
  if (error)
 
791
    release_ddl_log_memory_entry(*active_entry);
 
792
  DBUG_RETURN(error);
 
793
}
 
794
 
 
795
 
 
796
/*
 
797
  Write final entry in the ddl log
 
798
  SYNOPSIS
 
799
    write_execute_ddl_log_entry()
 
800
    first_entry                    First entry in linked list of entries
 
801
                                   to execute, if 0 = NULL it means that
 
802
                                   the entry is removed and the entries
 
803
                                   are put into the free list.
 
804
    complete                       Flag indicating we are simply writing
 
805
                                   info about that entry has been completed
 
806
    in:out:active_entry            Entry to execute, 0 = NULL if the entry
 
807
                                   is written first time and needs to be
 
808
                                   returned. In this case the entry written
 
809
                                   is returned in this parameter
 
810
  RETURN VALUES
 
811
    true                           Error
 
812
    false                          Success
 
813
 
 
814
  DESCRIPTION
 
815
    This is the last write in the ddl log. The previous log entries have
 
816
    already been written but not yet synched to disk.
 
817
    We write a couple of log entries that describes action to perform.
 
818
    This entries are set-up in a linked list, however only when a first
 
819
    execute entry is put as the first entry these will be executed.
 
820
    This routine writes this first 
 
821
*/ 
 
822
 
 
823
bool write_execute_ddl_log_entry(uint first_entry,
 
824
                                 bool complete,
 
825
                                 DDL_LOG_MEMORY_ENTRY **active_entry)
 
826
{
 
827
  bool write_header= false;
 
828
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
829
  DBUG_ENTER("write_execute_ddl_log_entry");
 
830
 
 
831
  if (init_ddl_log())
 
832
  {
 
833
    DBUG_RETURN(true);
 
834
  }
 
835
  if (!complete)
 
836
  {
 
837
    /*
 
838
      We haven't synched the log entries yet, we synch them now before
 
839
      writing the execute entry. If complete is true we haven't written
 
840
      any log entries before, we are only here to write the execute
 
841
      entry to indicate it is done.
 
842
    */
 
843
    VOID(sync_ddl_log());
 
844
    file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
 
845
  }
 
846
  else
 
847
    file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
 
848
  file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
 
849
  file_entry_buf[DDL_LOG_PHASE_POS]= 0;
 
850
  int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
 
851
  file_entry_buf[DDL_LOG_NAME_POS]= 0;
 
852
  file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
 
853
  file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
 
854
  if (!(*active_entry))
 
855
  {
 
856
    if (get_free_ddl_log_entry(active_entry, &write_header))
 
857
    {
 
858
      DBUG_RETURN(true);
 
859
    }
 
860
  }
 
861
  if (write_ddl_log_file_entry((*active_entry)->entry_pos))
 
862
  {
 
863
    sql_print_error("Error writing execute entry in ddl log");
 
864
    release_ddl_log_memory_entry(*active_entry);
 
865
    DBUG_RETURN(true);
 
866
  }
 
867
  VOID(sync_ddl_log());
 
868
  if (write_header)
 
869
  {
 
870
    if (write_ddl_log_header())
 
871
    {
 
872
      release_ddl_log_memory_entry(*active_entry);
 
873
      DBUG_RETURN(true);
 
874
    }
 
875
  }
 
876
  DBUG_RETURN(false);
 
877
}
 
878
 
 
879
 
 
880
/*
 
881
  For complex rename operations we need to deactivate individual entries.
 
882
  SYNOPSIS
 
883
    deactivate_ddl_log_entry()
 
884
    entry_no                      Entry position of record to change
 
885
  RETURN VALUES
 
886
    true                         Error
 
887
    false                        Success
 
888
  DESCRIPTION
 
889
    During replace operations where we start with an existing table called
 
890
    t1 and a replacement table called t1#temp or something else and where
 
891
    we want to delete t1 and rename t1#temp to t1 this is not possible to
 
892
    do in a safe manner unless the ddl log is informed of the phases in
 
893
    the change.
 
894
 
 
895
    Delete actions are 1-phase actions that can be ignored immediately after
 
896
    being executed.
 
897
    Rename actions from x to y is also a 1-phase action since there is no
 
898
    interaction with any other handlers named x and y.
 
899
    Replace action where drop y and x -> y happens needs to be a two-phase
 
900
    action. Thus the first phase will drop y and the second phase will
 
901
    rename x -> y.
 
902
*/
 
903
 
 
904
bool deactivate_ddl_log_entry(uint entry_no)
 
905
{
 
906
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
907
  DBUG_ENTER("deactivate_ddl_log_entry");
 
908
 
 
909
  if (!read_ddl_log_file_entry(entry_no))
 
910
  {
 
911
    if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
 
912
    {
 
913
      if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
 
914
          file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
 
915
          (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
 
916
           file_entry_buf[DDL_LOG_PHASE_POS] == 1))
 
917
        file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
 
918
      else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
 
919
      {
 
920
        DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
 
921
        file_entry_buf[DDL_LOG_PHASE_POS]= 1;
 
922
      }
 
923
      else
 
924
      {
 
925
        DBUG_ASSERT(0);
 
926
      }
 
927
      if (write_ddl_log_file_entry(entry_no))
 
928
      {
 
929
        sql_print_error("Error in deactivating log entry. Position = %u",
 
930
                        entry_no);
 
931
        DBUG_RETURN(true);
 
932
      }
 
933
    }
 
934
  }
 
935
  else
 
936
  {
 
937
    sql_print_error("Failed in reading entry before deactivating it");
 
938
    DBUG_RETURN(true);
 
939
  }
 
940
  DBUG_RETURN(false);
 
941
}
 
942
 
 
943
 
 
944
/*
 
945
  Sync ddl log file
 
946
  SYNOPSIS
 
947
    sync_ddl_log()
 
948
  RETURN VALUES
 
949
    true                      Error
 
950
    false                     Success
 
951
*/
 
952
 
 
953
bool sync_ddl_log()
 
954
{
 
955
  bool error= false;
 
956
  DBUG_ENTER("sync_ddl_log");
 
957
 
 
958
  if ((!global_ddl_log.recovery_phase) &&
 
959
      init_ddl_log())
 
960
  {
 
961
    DBUG_RETURN(true);
 
962
  }
 
963
  if (my_sync(global_ddl_log.file_id, MYF(0)))
 
964
  {
 
965
    /* Write to error log */
 
966
    sql_print_error("Failed to sync ddl log");
 
967
    error= true;
 
968
  }
 
969
  DBUG_RETURN(error);
 
970
}
 
971
 
 
972
 
 
973
/*
 
974
  Release a log memory entry
 
975
  SYNOPSIS
 
976
    release_ddl_log_memory_entry()
 
977
    log_memory_entry                Log memory entry to release
 
978
  RETURN VALUES
 
979
    NONE
 
980
*/
 
981
 
 
982
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
 
983
{
 
984
  DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
 
985
  DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
 
986
  DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
 
987
  DBUG_ENTER("release_ddl_log_memory_entry");
 
988
 
 
989
  global_ddl_log.first_free= log_entry;
 
990
  log_entry->next_log_entry= first_free;
 
991
 
 
992
  if (prev_log_entry)
 
993
    prev_log_entry->next_log_entry= next_log_entry;
 
994
  else
 
995
    global_ddl_log.first_used= next_log_entry;
 
996
  if (next_log_entry)
 
997
    next_log_entry->prev_log_entry= prev_log_entry;
 
998
  DBUG_VOID_RETURN;
 
999
}
 
1000
 
 
1001
 
 
1002
/*
 
1003
  Execute one entry in the ddl log. Executing an entry means executing
 
1004
  a linked list of actions.
 
1005
  SYNOPSIS
 
1006
    execute_ddl_log_entry()
 
1007
    first_entry                Reference to first action in entry
 
1008
  RETURN VALUES
 
1009
    true                       Error
 
1010
    false                      Success
 
1011
*/
 
1012
 
 
1013
bool execute_ddl_log_entry(THD *thd, uint first_entry)
 
1014
{
 
1015
  DDL_LOG_ENTRY ddl_log_entry;
 
1016
  uint read_entry= first_entry;
 
1017
  DBUG_ENTER("execute_ddl_log_entry");
 
1018
 
 
1019
  pthread_mutex_lock(&LOCK_gdl);
 
1020
  do
 
1021
  {
 
1022
    if (read_ddl_log_entry(read_entry, &ddl_log_entry))
 
1023
    {
 
1024
      /* Write to error log and continue with next log entry */
 
1025
      sql_print_error("Failed to read entry = %u from ddl log",
 
1026
                      read_entry);
 
1027
      break;
 
1028
    }
 
1029
    DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
 
1030
                ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
 
1031
 
 
1032
    if (execute_ddl_log_action(thd, &ddl_log_entry))
 
1033
    {
 
1034
      /* Write to error log and continue with next log entry */
 
1035
      sql_print_error("Failed to execute action for entry = %u from ddl log",
 
1036
                      read_entry);
 
1037
      break;
 
1038
    }
 
1039
    read_entry= ddl_log_entry.next_entry;
 
1040
  } while (read_entry);
 
1041
  pthread_mutex_unlock(&LOCK_gdl);
 
1042
  DBUG_RETURN(false);
 
1043
}
 
1044
 
 
1045
 
 
1046
/*
 
1047
  Close the ddl log
 
1048
  SYNOPSIS
 
1049
    close_ddl_log()
 
1050
  RETURN VALUES
 
1051
    NONE
 
1052
*/
 
1053
 
 
1054
static void close_ddl_log()
 
1055
{
 
1056
  DBUG_ENTER("close_ddl_log");
 
1057
  if (global_ddl_log.file_id >= 0)
 
1058
  {
 
1059
    VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
 
1060
    global_ddl_log.file_id= (File) -1;
 
1061
  }
 
1062
  DBUG_VOID_RETURN;
 
1063
}
 
1064
 
 
1065
 
 
1066
/*
 
1067
  Execute the ddl log at recovery of MySQL Server
 
1068
  SYNOPSIS
 
1069
    execute_ddl_log_recovery()
 
1070
  RETURN VALUES
 
1071
    NONE
 
1072
*/
 
1073
 
 
1074
void execute_ddl_log_recovery()
 
1075
{
 
1076
  uint num_entries, i;
 
1077
  THD *thd;
 
1078
  DDL_LOG_ENTRY ddl_log_entry;
 
1079
  char file_name[FN_REFLEN];
 
1080
  DBUG_ENTER("execute_ddl_log_recovery");
 
1081
 
 
1082
  /*
 
1083
    Initialise global_ddl_log struct
 
1084
  */
 
1085
  bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
 
1086
  global_ddl_log.inited= false;
 
1087
  global_ddl_log.recovery_phase= true;
 
1088
  global_ddl_log.io_size= IO_SIZE;
 
1089
  global_ddl_log.file_id= (File) -1;
 
1090
 
 
1091
  /*
 
1092
    To be able to run this from boot, we allocate a temporary THD
 
1093
  */
 
1094
  if (!(thd=new THD))
 
1095
    DBUG_VOID_RETURN;
 
1096
  thd->thread_stack= (char*) &thd;
 
1097
  thd->store_globals();
 
1098
 
 
1099
  num_entries= read_ddl_log_header();
 
1100
  for (i= 1; i < num_entries + 1; i++)
 
1101
  {
 
1102
    if (read_ddl_log_entry(i, &ddl_log_entry))
 
1103
    {
 
1104
      sql_print_error("Failed to read entry no = %u from ddl log",
 
1105
                       i);
 
1106
      continue;
 
1107
    }
 
1108
    if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
 
1109
    {
 
1110
      if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
 
1111
      {
 
1112
        /* Real unpleasant scenario but we continue anyways.  */
 
1113
        continue;
 
1114
      }
 
1115
    }
 
1116
  }
 
1117
  close_ddl_log();
 
1118
  create_ddl_log_file_name(file_name);
 
1119
  VOID(my_delete(file_name, MYF(0)));
 
1120
  global_ddl_log.recovery_phase= false;
 
1121
  delete thd;
 
1122
  /* Remember that we don't have a THD */
 
1123
  my_pthread_setspecific_ptr(THR_THD,  0);
 
1124
  DBUG_VOID_RETURN;
 
1125
}
 
1126
 
 
1127
 
 
1128
/*
 
1129
  Release all memory allocated to the ddl log
 
1130
  SYNOPSIS
 
1131
    release_ddl_log()
 
1132
  RETURN VALUES
 
1133
    NONE
 
1134
*/
 
1135
 
 
1136
void release_ddl_log()
 
1137
{
 
1138
  DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
 
1139
  DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
 
1140
  DBUG_ENTER("release_ddl_log");
 
1141
 
 
1142
  if (!global_ddl_log.do_release)
 
1143
    DBUG_VOID_RETURN;
 
1144
 
 
1145
  pthread_mutex_lock(&LOCK_gdl);
 
1146
  while (used_list)
 
1147
  {
 
1148
    DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
 
1149
    my_free(used_list, MYF(0));
 
1150
    used_list= tmp;
 
1151
  }
 
1152
  while (free_list)
 
1153
  {
 
1154
    DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
 
1155
    my_free(free_list, MYF(0));
 
1156
    free_list= tmp;
 
1157
  }
 
1158
  close_ddl_log();
 
1159
  global_ddl_log.inited= 0;
 
1160
  pthread_mutex_unlock(&LOCK_gdl);
 
1161
  VOID(pthread_mutex_destroy(&LOCK_gdl));
 
1162
  global_ddl_log.do_release= false;
 
1163
  DBUG_VOID_RETURN;
 
1164
}
 
1165
 
 
1166
 
 
1167
/*
 
1168
---------------------------------------------------------------------------
 
1169
 
 
1170
  END MODULE DDL log
 
1171
  --------------------
 
1172
 
 
1173
---------------------------------------------------------------------------
 
1174
*/
 
1175
 
92
1176
 
93
1177
/*
94
1178
  SYNOPSIS
95
1179
    write_bin_log()
96
 
    session                           Thread object
 
1180
    thd                           Thread object
 
1181
    clear_error                   is clear_error to be called
97
1182
    query                         Query to log
98
1183
    query_length                  Length of query
99
1184
 
102
1187
 
103
1188
  DESCRIPTION
104
1189
    Write the binlog if open, routine used in multiple places in this
105
 
    cursor
106
 
*/
107
 
 
108
 
void write_bin_log(Session *session,
109
 
                   char const *query)
110
 
{
111
 
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(session, query);
 
1190
    file
 
1191
*/
 
1192
 
 
1193
void write_bin_log(THD *thd, bool clear_error,
 
1194
                   char const *query, ulong query_length)
 
1195
{
 
1196
  if (mysql_bin_log.is_open())
 
1197
  {
 
1198
    if (clear_error)
 
1199
      thd->clear_error();
 
1200
    thd->binlog_query(THD::STMT_QUERY_TYPE,
 
1201
                      query, query_length, false, false);
 
1202
  }
 
1203
}
 
1204
 
 
1205
 
 
1206
/*
 
1207
 delete (drop) tables.
 
1208
 
 
1209
  SYNOPSIS
 
1210
   mysql_rm_table()
 
1211
   thd                  Thread handle
 
1212
   tables               List of tables to delete
 
1213
   if_exists            If 1, don't give error if one table doesn't exists
 
1214
 
 
1215
  NOTES
 
1216
    Will delete all tables that can be deleted and give a compact error
 
1217
    messages for tables that could not be deleted.
 
1218
    If a table is in use, we will wait for all users to free the table
 
1219
    before dropping it
 
1220
 
 
1221
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
1222
    not if under LOCK TABLES.
 
1223
 
 
1224
  RETURN
 
1225
    false OK.  In this case ok packet is sent to user
 
1226
    true  Error
 
1227
 
 
1228
*/
 
1229
 
 
1230
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
 
1231
                    my_bool drop_temporary)
 
1232
{
 
1233
  bool error, need_start_waiting= false;
 
1234
  DBUG_ENTER("mysql_rm_table");
 
1235
 
 
1236
  if (tables && tables->schema_table)
 
1237
  {
 
1238
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
1239
    DBUG_RETURN(true);
 
1240
  }
 
1241
 
 
1242
  /* mark for close and remove all cached entries */
 
1243
 
 
1244
  if (!drop_temporary)
 
1245
  {
 
1246
    if (!thd->locked_tables &&
 
1247
        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
 
1248
      DBUG_RETURN(true);
 
1249
  }
 
1250
 
 
1251
  /*
 
1252
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
1253
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
1254
    close their tables. This would make a pretty deadlock.
 
1255
  */
 
1256
  error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
 
1257
 
 
1258
  if (need_start_waiting)
 
1259
    start_waiting_global_read_lock(thd);
 
1260
 
 
1261
  if (error)
 
1262
    DBUG_RETURN(true);
 
1263
  my_ok(thd);
 
1264
  DBUG_RETURN(false);
113
1265
}
114
1266
 
115
1267
/*
117
1269
 
118
1270
  SYNOPSIS
119
1271
    mysql_rm_table_part2()
120
 
    session                     Thread Cursor
 
1272
    thd                 Thread handler
121
1273
    tables              Tables to drop
122
1274
    if_exists           If set, don't give an error if table doesn't exists.
123
1275
                        In this case we give an warning of level 'NOTE'
124
1276
    drop_temporary      Only drop temporary tables
 
1277
    drop_view           Allow to delete VIEW .frm
 
1278
    dont_log_query      Don't write query to log files. This will also not
 
1279
                        generate warnings if the handler files doesn't exists  
125
1280
 
126
 
  @todo
 
1281
  TODO:
127
1282
    When logging to the binary log, we should log
128
1283
    tmp_tables and transactional tables as separate statements if we
129
1284
    are in a transaction;  This is needed to get these tables into the
139
1294
   -1   Thread was killed
140
1295
*/
141
1296
 
142
 
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                         bool drop_temporary)
 
1297
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
 
1298
                         bool drop_temporary, bool drop_view,
 
1299
                         bool dont_log_query)
144
1300
{
145
 
  TableList *table;
 
1301
  TABLE_LIST *table;
 
1302
  char path[FN_REFLEN], *alias;
 
1303
  uint path_length;
146
1304
  String wrong_tables;
147
1305
  int error= 0;
148
 
  bool foreign_key_error= false;
149
 
 
150
 
  LOCK_open.lock(); /* Part 2 of rm a table */
 
1306
  int non_temp_tables_count= 0;
 
1307
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
 
1308
  String built_query;
 
1309
  DBUG_ENTER("mysql_rm_table_part2");
 
1310
 
 
1311
  if (thd->current_stmt_binlog_row_based && !dont_log_query)
 
1312
  {
 
1313
    built_query.set_charset(system_charset_info);
 
1314
    if (if_exists)
 
1315
      built_query.append("DROP TABLE IF EXISTS ");
 
1316
    else
 
1317
      built_query.append("DROP TABLE ");
 
1318
  }
 
1319
 
 
1320
  mysql_ha_rm_tables(thd, tables, false);
 
1321
 
 
1322
  pthread_mutex_lock(&LOCK_open);
151
1323
 
152
1324
  /*
153
1325
    If we have the table in the definition cache, we don't have to check the
154
 
    .frm cursor to find if the table is a normal table (not view) and what
 
1326
    .frm file to find if the table is a normal table (not view) and what
155
1327
    engine to use.
156
1328
  */
157
1329
 
158
1330
  for (table= tables; table; table= table->next_local)
159
1331
  {
160
 
    TableIdentifier identifier(table->db, table->table_name);
161
 
    TableShare *share;
162
 
    table->setDbType(NULL);
163
 
 
164
 
    if ((share= TableShare::getShare(identifier)))
165
 
    {
166
 
      table->setDbType(share->db_type());
167
 
    }
 
1332
    TABLE_SHARE *share;
 
1333
    table->db_type= NULL;
 
1334
    if ((share= get_cached_table_share(table->db, table->table_name)))
 
1335
      table->db_type= share->db_type();
168
1336
  }
169
1337
 
170
 
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
1338
  if (!drop_temporary && lock_table_names_exclusively(thd, tables))
171
1339
  {
172
 
    LOCK_open.unlock();
173
 
    return 1;
 
1340
    pthread_mutex_unlock(&LOCK_open);
 
1341
    DBUG_RETURN(1);
174
1342
  }
175
1343
 
176
1344
  /* Don't give warnings for not found errors, as we already generate notes */
177
 
  session->no_warnings_for_error= 1;
 
1345
  thd->no_warnings_for_error= 1;
178
1346
 
179
1347
  for (table= tables; table; table= table->next_local)
180
1348
  {
181
1349
    char *db=table->db;
182
 
 
183
 
    error= session->drop_temporary_table(table);
 
1350
    handlerton *table_type;
 
1351
    enum legacy_db_type frm_db_type;
 
1352
 
 
1353
    DBUG_PRINT("table", ("table_l: '%s'.'%s'  table: 0x%lx  s: 0x%lx",
 
1354
                         table->db, table->table_name, (long) table->table,
 
1355
                         table->table ? (long) table->table->s : (long) -1));
 
1356
 
 
1357
    error= drop_temporary_table(thd, table);
184
1358
 
185
1359
    switch (error) {
186
1360
    case  0:
187
1361
      // removed temporary table
 
1362
      tmp_table_deleted= 1;
188
1363
      continue;
189
1364
    case -1:
 
1365
      DBUG_ASSERT(thd->in_sub_stmt);
190
1366
      error= 1;
191
1367
      goto err_with_placeholders;
192
1368
    default:
194
1370
      error= 0;
195
1371
    }
196
1372
 
197
 
    if (drop_temporary == false)
198
 
    {
199
 
      Table *locked_table;
200
 
      TableIdentifier identifier(db, table->table_name);
201
 
      abort_locked_tables(session, identifier);
202
 
      remove_table_from_cache(session, identifier,
 
1373
    /*
 
1374
      If row-based replication is used and the table is not a
 
1375
      temporary table, we add the table name to the drop statement
 
1376
      being built.  The string always end in a comma and the comma
 
1377
      will be chopped off before being written to the binary log.
 
1378
      */
 
1379
    if (thd->current_stmt_binlog_row_based && !dont_log_query)
 
1380
    {
 
1381
      non_temp_tables_count++;
 
1382
      /*
 
1383
        Don't write the database name if it is the current one (or if
 
1384
        thd->db is NULL).
 
1385
      */
 
1386
      built_query.append("`");
 
1387
      if (thd->db == NULL || strcmp(db,thd->db) != 0)
 
1388
      {
 
1389
        built_query.append(db);
 
1390
        built_query.append("`.`");
 
1391
      }
 
1392
 
 
1393
      built_query.append(table->table_name);
 
1394
      built_query.append("`,");
 
1395
    }
 
1396
 
 
1397
    table_type= table->db_type;
 
1398
    if (!drop_temporary)
 
1399
    {
 
1400
      TABLE *locked_table;
 
1401
      abort_locked_tables(thd, db, table->table_name);
 
1402
      remove_table_from_cache(thd, db, table->table_name,
203
1403
                              RTFC_WAIT_OTHER_THREAD_FLAG |
204
1404
                              RTFC_CHECK_KILLED_FLAG);
205
1405
      /*
206
1406
        If the table was used in lock tables, remember it so that
207
1407
        unlock_table_names can free it
208
1408
      */
209
 
      if ((locked_table= drop_locked_tables(session, identifier)))
 
1409
      if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
210
1410
        table->table= locked_table;
211
1411
 
212
 
      if (session->killed)
 
1412
      if (thd->killed)
213
1413
      {
214
1414
        error= -1;
215
1415
        goto err_with_placeholders;
216
1416
      }
 
1417
      alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
 
1418
      /* remove .frm file and engine files */
 
1419
      path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
1420
                                        table->internal_tmp_table ?
 
1421
                                        FN_IS_TMP : 0);
217
1422
    }
218
 
    TableIdentifier identifier(db, table->table_name, table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
219
 
 
220
 
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
1423
    if (drop_temporary ||
 
1424
        ((table_type == NULL && (access(path, F_OK) && ha_create_table_from_engine(thd, db, alias))) ||
 
1425
         (!drop_view && mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
221
1426
    {
222
1427
      // Table was not found on disk and table can't be created from engine
223
1428
      if (if_exists)
224
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1429
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
225
1430
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
226
1431
                            table->table_name);
227
1432
      else
229
1434
    }
230
1435
    else
231
1436
    {
232
 
      error= plugin::StorageEngine::dropTable(*session, identifier);
233
 
 
234
 
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
235
 
      {
236
 
        error= 0;
237
 
        session->clear_error();
238
 
      }
239
 
 
 
1437
      char *end;
 
1438
      if (table_type == NULL)
 
1439
      {
 
1440
        mysql_frm_type(thd, path, &frm_db_type);
 
1441
        table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
 
1442
      }
 
1443
      // Remove extension for delete
 
1444
      *(end= path + path_length - reg_ext_length)= '\0';
 
1445
      error= ha_delete_table(thd, table_type, path, db, table->table_name,
 
1446
                             !dont_log_query);
 
1447
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && 
 
1448
          (if_exists || table_type == NULL))
 
1449
      {
 
1450
        error= 0;
 
1451
        thd->clear_error();
 
1452
      }
240
1453
      if (error == HA_ERR_ROW_IS_REFERENCED)
241
1454
      {
242
1455
        /* the table is referenced by a foreign key constraint */
243
 
        foreign_key_error= true;
244
 
      }
245
 
    }
246
 
 
247
 
    if (error == 0 || (if_exists && foreign_key_error == false))
248
 
    {
249
 
      TransactionServices &transaction_services= TransactionServices::singleton();
250
 
      transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
251
 
    }
252
 
 
 
1456
        foreign_key_error=1;
 
1457
      }
 
1458
      if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
 
1459
      {
 
1460
        int new_error;
 
1461
        /* Delete the table definition file */
 
1462
        strmov(end,reg_ext);
 
1463
        if (!(new_error=my_delete(path,MYF(MY_WME))))
 
1464
        {
 
1465
          some_tables_deleted=1;
 
1466
          new_error= 0;
 
1467
        }
 
1468
        error|= new_error;
 
1469
      }
 
1470
    }
253
1471
    if (error)
254
1472
    {
255
1473
      if (wrong_tables.length())
256
1474
        wrong_tables.append(',');
257
1475
      wrong_tables.append(String(table->table_name,system_charset_info));
258
1476
    }
 
1477
    DBUG_PRINT("table", ("table: 0x%lx  s: 0x%lx", (long) table->table,
 
1478
                         table->table ? (long) table->table->s : (long) -1));
259
1479
  }
260
1480
  /*
261
1481
    It's safe to unlock LOCK_open: we have an exclusive lock
262
1482
    on the table name.
263
1483
  */
264
 
  LOCK_open.unlock();
 
1484
  pthread_mutex_unlock(&LOCK_open);
 
1485
  thd->thread_specific_used|= tmp_table_deleted;
265
1486
  error= 0;
266
 
 
267
1487
  if (wrong_tables.length())
268
1488
  {
269
 
    if (not foreign_key_error)
270
 
    {
 
1489
    if (!foreign_key_error)
271
1490
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
272
1491
                      wrong_tables.c_ptr());
273
 
    }
274
1492
    else
275
 
    {
276
1493
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
 
1494
    error= 1;
 
1495
  }
 
1496
 
 
1497
  if (some_tables_deleted || tmp_table_deleted || !error)
 
1498
  {
 
1499
    if (!dont_log_query)
 
1500
    {
 
1501
      if (!thd->current_stmt_binlog_row_based ||
 
1502
          (non_temp_tables_count > 0 && !tmp_table_deleted))
 
1503
      {
 
1504
        /*
 
1505
          In this case, we are either using statement-based
 
1506
          replication or using row-based replication but have only
 
1507
          deleted one or more non-temporary tables (and no temporary
 
1508
          tables).  In this case, we can write the original query into
 
1509
          the binary log.
 
1510
         */
 
1511
        write_bin_log(thd, !error, thd->query, thd->query_length);
 
1512
      }
 
1513
      else if (thd->current_stmt_binlog_row_based &&
 
1514
               non_temp_tables_count > 0 &&
 
1515
               tmp_table_deleted)
 
1516
      {
 
1517
        /*
 
1518
          In this case we have deleted both temporary and
 
1519
          non-temporary tables, so:
 
1520
          - since we have deleted a non-temporary table we have to
 
1521
            binlog the statement, but
 
1522
          - since we have deleted a temporary table we cannot binlog
 
1523
            the statement (since the table has not been created on the
 
1524
            slave, this might cause the slave to stop).
 
1525
 
 
1526
          Instead, we write a built statement, only containing the
 
1527
          non-temporary tables, to the binary log
 
1528
        */
 
1529
        built_query.chop();                  // Chop of the last comma
 
1530
        built_query.append(" /* generated by server */");
 
1531
        write_bin_log(thd, !error, built_query.ptr(), built_query.length());
 
1532
      }
 
1533
      /*
 
1534
        The remaining cases are:
 
1535
        - no tables where deleted and
 
1536
        - only temporary tables where deleted and row-based
 
1537
          replication is used.
 
1538
        In both these cases, nothing should be written to the binary
 
1539
        log.
 
1540
      */
277
1541
    }
278
 
    error= 1;
279
1542
  }
280
 
 
281
 
  LOCK_open.lock(); /* final bit in rm table lock */
282
 
 
 
1543
  pthread_mutex_lock(&LOCK_open);
283
1544
err_with_placeholders:
284
 
  unlock_table_names(tables, NULL);
285
 
  LOCK_open.unlock();
286
 
  session->no_warnings_for_error= 0;
287
 
 
288
 
  return error;
 
1545
  unlock_table_names(thd, tables, (TABLE_LIST*) 0);
 
1546
  pthread_mutex_unlock(&LOCK_open);
 
1547
  thd->no_warnings_for_error= 0;
 
1548
  DBUG_RETURN(error);
289
1549
}
290
1550
 
291
1551
 
294
1554
 
295
1555
  SYNOPSIS
296
1556
    quick_rm_table()
297
 
      base                      The plugin::StorageEngine handle.
 
1557
      base                      The handlerton handle.
298
1558
      db                        The database name.
299
1559
      table_name                The table name.
300
 
      is_tmp                    If the table is temp.
 
1560
      flags                     flags for build_table_filename().
301
1561
 
302
1562
  RETURN
303
1563
    0           OK
304
1564
    != 0        Error
305
1565
*/
306
 
bool quick_rm_table(Session& session,
307
 
                    TableIdentifier &identifier)
 
1566
 
 
1567
bool quick_rm_table(handlerton *base,const char *db,
 
1568
                    const char *table_name, uint flags)
308
1569
{
309
 
  return (plugin::StorageEngine::dropTable(session, identifier));
 
1570
  char path[FN_REFLEN];
 
1571
  bool error= 0;
 
1572
  DBUG_ENTER("quick_rm_table");
 
1573
 
 
1574
  uint path_length= build_table_filename(path, sizeof(path),
 
1575
                                         db, table_name, reg_ext, flags);
 
1576
  if (my_delete(path,MYF(0)))
 
1577
    error= 1; /* purecov: inspected */
 
1578
  path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
 
1579
  DBUG_RETURN(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
 
1580
              error);
310
1581
}
311
1582
 
312
1583
/*
322
1593
  PRIMARY keys are prioritized.
323
1594
*/
324
1595
 
325
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
1596
static int sort_keys(KEY *a, KEY *b)
326
1597
{
327
1598
  ulong a_flags= a->flags, b_flags= b->flags;
328
 
 
 
1599
  
329
1600
  if (a_flags & HA_NOSAME)
330
1601
  {
331
1602
    if (!(b_flags & HA_NOSAME))
335
1606
      /* Sort NOT NULL keys before other keys */
336
1607
      return (a_flags & (HA_NULL_PART_KEY)) ? 1 : -1;
337
1608
    }
338
 
    if (is_primary_key(a))
 
1609
    if (a->name == primary_key_name)
339
1610
      return -1;
340
 
    if (is_primary_key(b))
 
1611
    if (b->name == primary_key_name)
341
1612
      return 1;
342
1613
    /* Sort keys don't containing partial segments before others */
343
1614
    if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
374
1645
    1             Error
375
1646
*/
376
1647
 
377
 
class typelib_set_member
378
 
{
379
 
public:
380
 
  string s;
381
 
  const CHARSET_INFO * const cs;
382
 
 
383
 
  typelib_set_member(const char* value, unsigned int length,
384
 
                     const CHARSET_INFO * const charset)
385
 
    : s(value, length),
386
 
      cs(charset)
387
 
  {}
388
 
};
389
 
 
390
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
391
 
{
392
 
  return (my_strnncoll(a.cs,
393
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
394
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
395
 
}
396
 
 
397
 
 
398
 
namespace
399
 
{
400
 
class typelib_set_member_hasher
401
 
{
402
 
  boost::hash<string> hasher;
403
 
public:
404
 
  std::size_t operator()(const typelib_set_member& t) const
405
 
  {
406
 
    return hasher(t.s);
407
 
  }
408
 
};
409
 
}
410
 
 
411
 
static bool check_duplicates_in_interval(const char *set_or_name,
412
 
                                         const char *name, TYPELIB *typelib,
413
 
                                         const CHARSET_INFO * const cs,
414
 
                                         unsigned int *dup_val_count)
 
1648
bool check_duplicates_in_interval(const char *set_or_name,
 
1649
                                  const char *name, TYPELIB *typelib,
 
1650
                                  CHARSET_INFO *cs, unsigned int *dup_val_count)
415
1651
{
416
1652
  TYPELIB tmp= *typelib;
417
1653
  const char **cur_value= typelib->type_names;
418
1654
  unsigned int *cur_length= typelib->type_lengths;
419
 
  *dup_val_count= 0;
420
 
 
421
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
422
 
 
423
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
1655
  *dup_val_count= 0;  
 
1656
  
 
1657
  for ( ; tmp.count > 1; cur_value++, cur_length++)
424
1658
  {
425
1659
    tmp.type_names++;
426
1660
    tmp.type_lengths++;
427
1661
    tmp.count--;
428
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
1662
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
429
1663
    {
430
1664
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
431
1665
               name,*cur_value,set_or_name);
432
1666
      return 1;
433
1667
    }
434
 
    else
435
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
436
1668
  }
437
1669
  return 0;
438
1670
}
456
1688
  RETURN VALUES
457
1689
    void
458
1690
*/
459
 
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
460
 
                                       TYPELIB *interval,
461
 
                                       uint32_t *max_length,
462
 
                                       uint32_t *tot_length)
 
1691
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
 
1692
                                uint32 *max_length, uint32 *tot_length)
463
1693
{
464
1694
  const char **pos;
465
 
  uint32_t *len;
 
1695
  uint *len;
466
1696
  *max_length= *tot_length= 0;
467
1697
  for (pos= interval->type_names, len= interval->type_lengths;
468
1698
       *pos ; pos++, len++)
469
1699
  {
470
 
    uint32_t length= cs->cset->numchars(cs, *pos, *pos + *len);
 
1700
    uint length= cs->cset->numchars(cs, *pos, *pos + *len);
471
1701
    *tot_length+= length;
472
 
    set_if_bigger(*max_length, (uint32_t)length);
 
1702
    set_if_bigger(*max_length, (uint32)length);
473
1703
  }
474
1704
}
475
1705
 
 
1706
 
476
1707
/*
477
1708
  Prepare a create_table instance for packing
478
1709
 
481
1712
    sql_field     field to prepare for packing
482
1713
    blob_columns  count for BLOBs
483
1714
    timestamps    count for timestamps
 
1715
    table_flags   table flags
484
1716
 
485
1717
  DESCRIPTION
486
 
    This function prepares a CreateField instance.
 
1718
    This function prepares a Create_field instance.
487
1719
    Fields such as pack_flag are valid after this call.
488
1720
 
489
1721
  RETURN VALUES
490
1722
   0    ok
491
1723
   1    Error
492
1724
*/
493
 
int prepare_create_field(CreateField *sql_field,
494
 
                         uint32_t *blob_columns,
495
 
                         int *timestamps,
496
 
                         int *timestamps_with_niladic)
 
1725
 
 
1726
int prepare_create_field(Create_field *sql_field, 
 
1727
                         uint *blob_columns,
 
1728
                         int *timestamps, int *timestamps_with_niladic,
 
1729
                         longlong table_flags)
497
1730
{
498
1731
  unsigned int dup_val_count;
 
1732
  DBUG_ENTER("prepare_field");
499
1733
 
500
1734
  /*
501
1735
    This code came from mysql_prepare_create_table.
502
1736
    Indent preserved to make patching easier
503
1737
  */
504
 
  assert(sql_field->charset);
 
1738
  DBUG_ASSERT(sql_field->charset);
505
1739
 
506
1740
  switch (sql_field->sql_type) {
507
 
  case DRIZZLE_TYPE_BLOB:
508
 
    sql_field->length= 8; // Unireg field length
 
1741
  case MYSQL_TYPE_BLOB:
 
1742
  case MYSQL_TYPE_MEDIUM_BLOB:
 
1743
  case MYSQL_TYPE_TINY_BLOB:
 
1744
  case MYSQL_TYPE_LONG_BLOB:
 
1745
    sql_field->pack_flag=FIELDFLAG_BLOB |
 
1746
      pack_length_to_packflag(sql_field->pack_length -
 
1747
                              portable_sizeof_char_ptr);
 
1748
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1749
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1750
    sql_field->length=8;                        // Unireg field length
 
1751
    sql_field->unireg_check=Field::BLOB_FIELD;
509
1752
    (*blob_columns)++;
510
1753
    break;
511
 
  case DRIZZLE_TYPE_VARCHAR:
512
 
    break;
513
 
  case DRIZZLE_TYPE_ENUM:
514
 
    if (check_duplicates_in_interval("ENUM",
515
 
                                     sql_field->field_name,
516
 
                                     sql_field->interval,
517
 
                                     sql_field->charset,
518
 
                                     &dup_val_count))
519
 
      return 1;
520
 
    break;
521
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
522
 
  case DRIZZLE_TYPE_DATETIME:
523
 
  case DRIZZLE_TYPE_NULL:
524
 
    break;
525
 
  case DRIZZLE_TYPE_DECIMAL:
526
 
    break;
527
 
  case DRIZZLE_TYPE_TIMESTAMP:
 
1754
  case MYSQL_TYPE_VARCHAR:
 
1755
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
 
1756
    if (table_flags & HA_NO_VARCHAR)
 
1757
    {
 
1758
      /* convert VARCHAR to CHAR because handler is not yet up to date */
 
1759
      sql_field->sql_type=    MYSQL_TYPE_VAR_STRING;
 
1760
      sql_field->pack_length= calc_pack_length(sql_field->sql_type,
 
1761
                                               (uint) sql_field->length);
 
1762
      if ((sql_field->length / sql_field->charset->mbmaxlen) >
 
1763
          MAX_FIELD_CHARLENGTH)
 
1764
      {
 
1765
        my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
 
1766
                        MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
 
1767
        DBUG_RETURN(1);
 
1768
      }
 
1769
    }
 
1770
#endif
 
1771
    /* fall through */
 
1772
  case MYSQL_TYPE_STRING:
 
1773
    sql_field->pack_flag=0;
 
1774
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1775
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1776
    break;
 
1777
  case MYSQL_TYPE_ENUM:
 
1778
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
1779
      FIELDFLAG_INTERVAL;
 
1780
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1781
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1782
    sql_field->unireg_check=Field::INTERVAL_FIELD;
 
1783
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
 
1784
                                 sql_field->interval,
 
1785
                                     sql_field->charset, &dup_val_count))
 
1786
      DBUG_RETURN(1);
 
1787
    break;
 
1788
  case MYSQL_TYPE_SET:
 
1789
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
1790
      FIELDFLAG_BITFIELD;
 
1791
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1792
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1793
    sql_field->unireg_check=Field::BIT_FIELD;
 
1794
    if (check_duplicates_in_interval("SET",sql_field->field_name,
 
1795
                                 sql_field->interval,
 
1796
                                     sql_field->charset, &dup_val_count))
 
1797
      DBUG_RETURN(1);
 
1798
    /* Check that count of unique members is not more then 64 */
 
1799
    if (sql_field->interval->count -  dup_val_count > sizeof(longlong)*8)
 
1800
    {
 
1801
       my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
 
1802
       DBUG_RETURN(1);
 
1803
    }
 
1804
    break;
 
1805
  case MYSQL_TYPE_NEWDATE:  // Rest of string types
 
1806
  case MYSQL_TYPE_TIME:
 
1807
  case MYSQL_TYPE_DATETIME:
 
1808
  case MYSQL_TYPE_NULL:
 
1809
    sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
 
1810
    break;
 
1811
  case MYSQL_TYPE_NEWDECIMAL:
 
1812
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
1813
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
1814
                           FIELDFLAG_DECIMAL) |
 
1815
                          (sql_field->flags & ZEROFILL_FLAG ?
 
1816
                           FIELDFLAG_ZEROFILL : 0) |
 
1817
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
 
1818
    break;
 
1819
  case MYSQL_TYPE_TIMESTAMP:
528
1820
    /* We should replace old TIMESTAMP fields with their newer analogs */
529
1821
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
530
1822
    {
534
1826
        (*timestamps_with_niladic)++;
535
1827
      }
536
1828
      else
537
 
      {
538
1829
        sql_field->unireg_check= Field::NONE;
539
 
      }
540
1830
    }
541
1831
    else if (sql_field->unireg_check != Field::NONE)
542
1832
      (*timestamps_with_niladic)++;
544
1834
    (*timestamps)++;
545
1835
    /* fall-through */
546
1836
  default:
 
1837
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
1838
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
1839
                           FIELDFLAG_DECIMAL) |
 
1840
                          (sql_field->flags & ZEROFILL_FLAG ?
 
1841
                           FIELDFLAG_ZEROFILL : 0) |
 
1842
                          f_settype((uint) sql_field->sql_type) |
 
1843
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
547
1844
    break;
548
1845
  }
549
 
 
550
 
  return 0;
 
1846
  if (!(sql_field->flags & NOT_NULL_FLAG))
 
1847
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
 
1848
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
 
1849
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
 
1850
  DBUG_RETURN(0);
551
1851
}
552
1852
 
553
 
static int mysql_prepare_create_table(Session *session,
554
 
                                      HA_CREATE_INFO *create_info,
555
 
                                      message::Table &create_proto,
556
 
                                      AlterInfo *alter_info,
557
 
                                      bool tmp_table,
558
 
                                      uint32_t *db_options,
559
 
                                      KeyInfo **key_info_buffer,
560
 
                                      uint32_t *key_count,
561
 
                                      int select_field_count)
 
1853
/*
 
1854
  Preparation for table creation
 
1855
 
 
1856
  SYNOPSIS
 
1857
    mysql_prepare_create_table()
 
1858
      thd                       Thread object.
 
1859
      create_info               Create information (like MAX_ROWS).
 
1860
      alter_info                List of columns and indexes to create
 
1861
      tmp_table                 If a temporary table is to be created.
 
1862
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
 
1863
      file                      The handler for the new table.
 
1864
      key_info_buffer     OUT   An array of KEY structs for the indexes.
 
1865
      key_count           OUT   The number of elements in the array.
 
1866
      select_field_count        The number of fields coming from a select table.
 
1867
 
 
1868
  DESCRIPTION
 
1869
    Prepares the table and key structures for table creation.
 
1870
 
 
1871
  NOTES
 
1872
    sets create_info->varchar if the table has a varchar
 
1873
 
 
1874
  RETURN VALUES
 
1875
    false    OK
 
1876
    true     error
 
1877
*/
 
1878
 
 
1879
static int
 
1880
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 
1881
                           Alter_info *alter_info,
 
1882
                           bool tmp_table,
 
1883
                               uint *db_options,
 
1884
                               handler *file, KEY **key_info_buffer,
 
1885
                               uint *key_count, int select_field_count)
562
1886
{
563
1887
  const char    *key_name;
564
 
  CreateField   *sql_field,*dup_field;
 
1888
  Create_field  *sql_field,*dup_field;
565
1889
  uint          field,null_fields,blob_columns,max_key_length;
566
1890
  ulong         record_offset= 0;
567
 
  KeyInfo               *key_info;
568
 
  KeyPartInfo *key_part_info;
 
1891
  KEY           *key_info;
 
1892
  KEY_PART_INFO *key_part_info;
569
1893
  int           timestamps= 0, timestamps_with_niladic= 0;
570
1894
  int           field_no,dup_no;
571
1895
  int           select_field_pos,auto_increment=0;
572
 
  List_iterator<CreateField> it(alter_info->create_list);
573
 
  List_iterator<CreateField> it2(alter_info->create_list);
574
 
  uint32_t total_uneven_bit_length= 0;
575
 
 
576
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
 
1896
  List_iterator<Create_field> it(alter_info->create_list);
 
1897
  List_iterator<Create_field> it2(alter_info->create_list);
 
1898
  uint total_uneven_bit_length= 0;
 
1899
  DBUG_ENTER("mysql_prepare_create_table");
577
1900
 
578
1901
  select_field_pos= alter_info->create_list.elements - select_field_count;
579
1902
  null_fields=blob_columns=0;
580
 
  max_key_length= engine->max_key_length();
 
1903
  create_info->varchar= 0;
 
1904
  max_key_length= file->max_key_length();
581
1905
 
582
1906
  for (field_no=0; (sql_field=it++) ; field_no++)
583
1907
  {
584
 
    const CHARSET_INFO *save_cs;
 
1908
    CHARSET_INFO *save_cs;
585
1909
 
586
1910
    /*
587
1911
      Initialize length from its original value (number of characters),
592
1916
    if (!sql_field->charset)
593
1917
      sql_field->charset= create_info->default_table_charset;
594
1918
    /*
595
 
      table_charset is set in ALTER Table if we want change character set
 
1919
      table_charset is set in ALTER TABLE if we want change character set
596
1920
      for all varchar/char columns.
597
1921
      But the table charset must not affect the BLOB fields, so don't
598
1922
      allow to change my_charset_bin to somethig else.
602
1926
 
603
1927
    save_cs= sql_field->charset;
604
1928
    if ((sql_field->flags & BINCMP_FLAG) &&
605
 
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, MY_CS_BINSORT)))
 
1929
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
 
1930
                                                    MY_CS_BINSORT,MYF(0))))
606
1931
    {
607
1932
      char tmp[64];
608
 
      char *tmp_pos= tmp;
609
 
      strncpy(tmp_pos, save_cs->csname, sizeof(tmp)-4);
610
 
      tmp_pos+= strlen(tmp);
611
 
      strncpy(tmp_pos, STRING_WITH_LEN("_bin"));
 
1933
      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
 
1934
              STRING_WITH_LEN("_bin"));
612
1935
      my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
613
 
      return(true);
 
1936
      DBUG_RETURN(true);
614
1937
    }
615
1938
 
616
1939
    /*
617
1940
      Convert the default value from client character
618
1941
      set into the column character set if necessary.
619
1942
    */
620
 
    if (sql_field->def &&
 
1943
    if (sql_field->def && 
621
1944
        save_cs != sql_field->def->collation.collation &&
622
 
        (sql_field->sql_type == DRIZZLE_TYPE_ENUM))
 
1945
        (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
 
1946
         sql_field->sql_type == MYSQL_TYPE_STRING ||
 
1947
         sql_field->sql_type == MYSQL_TYPE_SET ||
 
1948
         sql_field->sql_type == MYSQL_TYPE_ENUM))
623
1949
    {
624
1950
      /*
625
 
        Starting from 5.1 we work here with a copy of CreateField
 
1951
        Starting from 5.1 we work here with a copy of Create_field
626
1952
        created by the caller, not with the instance that was
627
1953
        originally created during parsing. It's OK to create
628
1954
        a temporary item and initialize with it a member of the
637
1963
      {
638
1964
        /* Could not convert */
639
1965
        my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
640
 
        return(true);
 
1966
        DBUG_RETURN(true);
641
1967
      }
642
1968
    }
643
1969
 
644
 
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
 
1970
    if (sql_field->sql_type == MYSQL_TYPE_SET ||
 
1971
        sql_field->sql_type == MYSQL_TYPE_ENUM)
645
1972
    {
646
 
      uint32_t dummy;
647
 
      const CHARSET_INFO * const cs= sql_field->charset;
 
1973
      uint32 dummy;
 
1974
      CHARSET_INFO *cs= sql_field->charset;
648
1975
      TYPELIB *interval= sql_field->interval;
649
1976
 
650
1977
      /*
659
1986
          occupied memory at the same time when we free this
660
1987
          sql_field -- at the end of execution.
661
1988
        */
662
 
        interval= sql_field->interval= typelib(session->mem_root,
 
1989
        interval= sql_field->interval= typelib(thd->mem_root,
663
1990
                                               sql_field->interval_list);
664
 
 
665
1991
        List_iterator<String> int_it(sql_field->interval_list);
666
1992
        String conv, *tmp;
667
1993
        char comma_buf[4];
668
 
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
669
 
                                          (unsigned char*) comma_buf +
 
1994
        int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
 
1995
                                          (uchar*) comma_buf + 
670
1996
                                          sizeof(comma_buf));
671
 
        assert(comma_length > 0);
672
 
 
673
 
        for (uint32_t i= 0; (tmp= int_it++); i++)
 
1997
        DBUG_ASSERT(comma_length > 0);
 
1998
        for (uint i= 0; (tmp= int_it++); i++)
674
1999
        {
675
 
          uint32_t lengthsp;
 
2000
          uint lengthsp;
676
2001
          if (String::needs_conversion(tmp->length(), tmp->charset(),
677
2002
                                       cs, &dummy))
678
2003
          {
679
 
            uint32_t cnv_errs;
 
2004
            uint cnv_errs;
680
2005
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
681
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
2006
            interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
 
2007
                                                  conv.length());
682
2008
            interval->type_lengths[i]= conv.length();
683
2009
          }
684
2010
 
686
2012
          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
687
2013
                                       interval->type_lengths[i]);
688
2014
          interval->type_lengths[i]= lengthsp;
689
 
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
 
2015
          ((uchar *)interval->type_names[i])[lengthsp]= '\0';
 
2016
          if (sql_field->sql_type == MYSQL_TYPE_SET)
 
2017
          {
 
2018
            if (cs->coll->instr(cs, interval->type_names[i], 
 
2019
                                interval->type_lengths[i], 
 
2020
                                comma_buf, comma_length, NULL, 0))
 
2021
            {
 
2022
              my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
 
2023
              DBUG_RETURN(true);
 
2024
            }
 
2025
          }
690
2026
        }
691
2027
        sql_field->interval_list.empty(); // Don't need interval_list anymore
692
2028
      }
693
2029
 
694
 
      /* DRIZZLE_TYPE_ENUM */
695
 
      {
696
 
        uint32_t field_length;
697
 
        assert(sql_field->sql_type == DRIZZLE_TYPE_ENUM);
698
 
        if (sql_field->def != NULL)
699
 
        {
700
 
          String str, *def= sql_field->def->val_str(&str);
701
 
          if (def == NULL) /* SQL "NULL" maps to NULL */
702
 
          {
703
 
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
704
 
            {
705
 
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
706
 
              return(true);
 
2030
      if (sql_field->sql_type == MYSQL_TYPE_SET)
 
2031
      {
 
2032
        uint32 field_length;
 
2033
        if (sql_field->def != NULL)
 
2034
        {
 
2035
          char *not_used;
 
2036
          uint not_used2;
 
2037
          bool not_found= 0;
 
2038
          String str, *def= sql_field->def->val_str(&str);
 
2039
          if (def == NULL) /* SQL "NULL" maps to NULL */
 
2040
          {
 
2041
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
 
2042
            {
 
2043
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
 
2044
              DBUG_RETURN(true);
 
2045
            }
 
2046
 
 
2047
            /* else, NULL is an allowed value */
 
2048
            (void) find_set(interval, NULL, 0,
 
2049
                            cs, &not_used, &not_used2, &not_found);
 
2050
          }
 
2051
          else /* not NULL */
 
2052
          {
 
2053
            (void) find_set(interval, def->ptr(), def->length(),
 
2054
                            cs, &not_used, &not_used2, &not_found);
 
2055
          }
 
2056
 
 
2057
          if (not_found)
 
2058
          {
 
2059
            my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
 
2060
            DBUG_RETURN(true);
 
2061
          }
 
2062
        }
 
2063
        calculate_interval_lengths(cs, interval, &dummy, &field_length);
 
2064
        sql_field->length= field_length + (interval->count - 1);
 
2065
      }
 
2066
      else  /* MYSQL_TYPE_ENUM */
 
2067
      {
 
2068
        uint32 field_length;
 
2069
        DBUG_ASSERT(sql_field->sql_type == MYSQL_TYPE_ENUM);
 
2070
        if (sql_field->def != NULL)
 
2071
        {
 
2072
          String str, *def= sql_field->def->val_str(&str);
 
2073
          if (def == NULL) /* SQL "NULL" maps to NULL */
 
2074
          {
 
2075
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
 
2076
            {
 
2077
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
 
2078
              DBUG_RETURN(true);
707
2079
            }
708
2080
 
709
2081
            /* else, the defaults yield the correct length for NULLs. */
710
 
          }
 
2082
          } 
711
2083
          else /* not NULL */
712
2084
          {
713
2085
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
714
2086
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
715
2087
            {
716
2088
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
717
 
              return(true);
 
2089
              DBUG_RETURN(true);
718
2090
            }
719
2091
          }
720
2092
        }
721
2093
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
722
2094
        sql_field->length= field_length;
723
2095
      }
724
 
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
 
2096
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
725
2097
    }
726
2098
 
727
2099
    sql_field->create_length_to_internal_length();
728
 
    if (prepare_blob_field(session, sql_field))
729
 
      return(true);
 
2100
    if (prepare_blob_field(thd, sql_field))
 
2101
      DBUG_RETURN(true);
730
2102
 
731
2103
    if (!(sql_field->flags & NOT_NULL_FLAG))
732
2104
      null_fields++;
734
2106
    if (check_column_name(sql_field->field_name))
735
2107
    {
736
2108
      my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
737
 
      return(true);
 
2109
      DBUG_RETURN(true);
738
2110
    }
739
2111
 
740
2112
    /* Check if we have used the same field name before */
751
2123
        if (field_no < select_field_pos || dup_no >= select_field_pos)
752
2124
        {
753
2125
          my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
754
 
          return(true);
 
2126
          DBUG_RETURN(true);
755
2127
        }
756
2128
        else
757
2129
        {
767
2139
          sql_field->decimals=          dup_field->decimals;
768
2140
          sql_field->create_length_to_internal_length();
769
2141
          sql_field->unireg_check=      dup_field->unireg_check;
770
 
          /*
 
2142
          /* 
771
2143
            We're making one field from two, the result field will have
772
2144
            dup_field->flags as flags. If we've incremented null_fields
773
2145
            because of sql_field->flags, decrement it back.
782
2154
        }
783
2155
      }
784
2156
    }
785
 
 
786
 
    /** @todo Get rid of this MyISAM-specific crap. */
787
 
    if (not create_proto.engine().name().compare("MyISAM") &&
788
 
        ((sql_field->flags & BLOB_FLAG) ||
789
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
 
2157
    /* Don't pack rows in old tables if the user has requested this */
 
2158
    if ((sql_field->flags & BLOB_FLAG) ||
 
2159
        (sql_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
790
2160
      (*db_options)|= HA_OPTION_PACK_RECORD;
791
2161
    it2.rewind();
792
2162
  }
798
2168
  it.rewind();
799
2169
  while ((sql_field=it++))
800
2170
  {
801
 
    assert(sql_field->charset != 0);
 
2171
    DBUG_ASSERT(sql_field->charset != 0);
802
2172
 
803
 
    if (prepare_create_field(sql_field, &blob_columns,
804
 
                             &timestamps, &timestamps_with_niladic))
805
 
      return(true);
 
2173
    if (prepare_create_field(sql_field, &blob_columns, 
 
2174
                             &timestamps, &timestamps_with_niladic,
 
2175
                             file->ha_table_flags()))
 
2176
      DBUG_RETURN(true);
 
2177
    if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
 
2178
      create_info->varchar= true;
806
2179
    sql_field->offset= record_offset;
807
2180
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
808
2181
      auto_increment++;
 
2182
    record_offset+= sql_field->pack_length;
809
2183
  }
810
2184
  if (timestamps_with_niladic > 1)
811
2185
  {
812
2186
    my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
813
2187
               ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
814
 
    return(true);
 
2188
    DBUG_RETURN(true);
815
2189
  }
816
2190
  if (auto_increment > 1)
817
2191
  {
818
2192
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
819
 
    return(true);
 
2193
    DBUG_RETURN(true);
820
2194
  }
821
2195
  if (auto_increment &&
822
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
2196
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
823
2197
  {
824
2198
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
825
2199
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
826
 
    return(true);
 
2200
    DBUG_RETURN(true);
827
2201
  }
828
2202
 
829
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
2203
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
830
2204
  {
831
2205
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
832
2206
               MYF(0));
833
 
    return(true);
 
2207
    DBUG_RETURN(true);
834
2208
  }
835
2209
 
836
2210
  /* Create keys */
837
2211
 
838
2212
  List_iterator<Key> key_iterator(alter_info->key_list);
839
2213
  List_iterator<Key> key_iterator2(alter_info->key_list);
840
 
  uint32_t key_parts=0, fk_key_count=0;
 
2214
  uint key_parts=0, fk_key_count=0;
841
2215
  bool primary_key=0,unique_key=0;
842
2216
  Key *key, *key2;
843
 
  uint32_t tmp, key_number;
 
2217
  uint tmp, key_number;
844
2218
  /* special marker for keys to be ignored */
845
2219
  static char ignore_key[1];
846
2220
 
849
2223
 
850
2224
  while ((key=key_iterator++))
851
2225
  {
 
2226
    DBUG_PRINT("info", ("key name: '%s'  type: %d", key->name.str ? key->name.str :
 
2227
                        "(none)" , key->type));
852
2228
    if (key->type == Key::FOREIGN_KEY)
853
2229
    {
854
2230
      fk_key_count++;
855
 
      if (((Foreign_key *)key)->validate(alter_info->create_list))
856
 
        return true;
857
 
 
858
2231
      Foreign_key *fk_key= (Foreign_key*) key;
859
 
 
860
 
      add_foreign_key_to_table_message(&create_proto,
861
 
                                       fk_key->name.str,
862
 
                                       fk_key->columns,
863
 
                                       fk_key->ref_table,
864
 
                                       fk_key->ref_columns,
865
 
                                       fk_key->delete_opt,
866
 
                                       fk_key->update_opt,
867
 
                                       fk_key->match_opt);
868
 
 
869
2232
      if (fk_key->ref_columns.elements &&
870
2233
          fk_key->ref_columns.elements != fk_key->columns.elements)
871
2234
      {
873
2236
                 (fk_key->name.str ? fk_key->name.str :
874
2237
                                     "foreign key without name"),
875
2238
                 ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
876
 
        return(true);
 
2239
        DBUG_RETURN(true);
877
2240
      }
878
2241
      continue;
879
2242
    }
880
2243
    (*key_count)++;
881
 
    tmp= engine->max_key_parts();
 
2244
    tmp=file->max_key_parts();
882
2245
    if (key->columns.elements > tmp)
883
2246
    {
884
2247
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
885
 
      return(true);
 
2248
      DBUG_RETURN(true);
886
2249
    }
887
2250
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
888
 
      return(true);
 
2251
      DBUG_RETURN(true);
889
2252
    key_iterator2.rewind ();
890
2253
    if (key->type != Key::FOREIGN_KEY)
891
2254
    {
900
2263
             key2->name.str != ignore_key &&
901
2264
             !foreign_key_prefix(key, key2)))
902
2265
        {
903
 
          /* @todo issue warning message */
 
2266
          /* TODO: issue warning message */
904
2267
          /* mark that the generated key should be ignored */
905
2268
          if (!key2->generated ||
906
2269
              (key->generated && key->columns.elements <
921
2284
    else
922
2285
      (*key_count)--;
923
2286
    if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
924
 
        is_primary_key_name(key->name.str))
 
2287
        !my_strcasecmp(system_charset_info,key->name.str, primary_key_name))
925
2288
    {
926
2289
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
927
 
      return(true);
 
2290
      DBUG_RETURN(true);
928
2291
    }
929
2292
  }
930
 
  tmp= engine->max_keys();
 
2293
  tmp=file->max_keys();
931
2294
  if (*key_count > tmp)
932
2295
  {
933
2296
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
934
 
    return(true);
 
2297
    DBUG_RETURN(true);
935
2298
  }
936
2299
 
937
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
938
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
2300
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
2301
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
939
2302
  if (!*key_info_buffer || ! key_part_info)
940
 
    return(true);                               // Out of memory
 
2303
    DBUG_RETURN(true);                          // Out of memory
941
2304
 
942
2305
  key_iterator.rewind();
943
2306
  key_number=0;
944
2307
  for (; (key=key_iterator++) ; key_number++)
945
2308
  {
946
 
    uint32_t key_length=0;
 
2309
    uint key_length=0;
947
2310
    Key_part_spec *column;
948
2311
 
949
2312
    if (key->name.str == ignore_key)
970
2333
    if (key->generated)
971
2334
      key_info->flags|= HA_GENERATED_KEY;
972
2335
 
973
 
    key_info->key_parts=(uint8_t) key->columns.elements;
 
2336
    key_info->key_parts=(uint8) key->columns.elements;
974
2337
    key_info->key_part=key_part_info;
975
2338
    key_info->usable_key_parts= key_number;
976
2339
    key_info->algorithm= key->key_create_info.algorithm;
977
2340
 
978
 
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
 
2341
    /* Take block size from key part or table part */
 
2342
    /*
 
2343
      TODO: Add warning if block size changes. We can't do it here, as
 
2344
      this may depend on the size of the key
 
2345
    */
 
2346
    key_info->block_size= (key->key_create_info.block_size ?
 
2347
                           key->key_create_info.block_size :
 
2348
                           create_info->key_block_size);
 
2349
 
 
2350
    if (key_info->block_size)
 
2351
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
2352
 
 
2353
    uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
979
2354
                                           key->key_create_info.comment.str,
980
2355
                                           key->key_create_info.comment.str +
981
2356
                                           key->key_create_info.comment.length,
985
2360
    {
986
2361
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
987
2362
               key->key_create_info.comment.str,"INDEX COMMENT",
988
 
               (uint32_t) INDEX_COMMENT_MAXLEN);
989
 
      return -1;
 
2363
               (uint) INDEX_COMMENT_MAXLEN);
 
2364
      DBUG_RETURN(-1);
990
2365
    }
991
2366
 
992
2367
    key_info->comment.length= key->key_create_info.comment.length;
996
2371
      key_info->comment.str= key->key_create_info.comment.str;
997
2372
    }
998
2373
 
999
 
    message::Table::Field *protofield= NULL;
1000
 
 
1001
2374
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
1002
 
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
 
2375
    for (uint column_nr=0 ; (column=cols++) ; column_nr++)
1003
2376
    {
1004
 
      uint32_t length;
 
2377
      uint length;
1005
2378
      Key_part_spec *dup_column;
1006
 
      int proto_field_nr= 0;
1007
2379
 
1008
2380
      it.rewind();
1009
2381
      field=0;
1010
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
2382
      while ((sql_field=it++) &&
1011
2383
             my_strcasecmp(system_charset_info,
1012
2384
                           column->field_name.str,
1013
2385
                           sql_field->field_name))
1015
2387
      if (!sql_field)
1016
2388
      {
1017
2389
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1018
 
        return(true);
 
2390
        DBUG_RETURN(true);
1019
2391
      }
1020
2392
      while ((dup_column= cols2++) != column)
1021
2393
      {
1022
2394
        if (!my_strcasecmp(system_charset_info,
1023
 
                           column->field_name.str, dup_column->field_name.str))
 
2395
                           column->field_name.str, dup_column->field_name.str))
1024
2396
        {
1025
2397
          my_printf_error(ER_DUP_FIELDNAME,
1026
2398
                          ER(ER_DUP_FIELDNAME),MYF(0),
1027
2399
                          column->field_name.str);
1028
 
          return(true);
 
2400
          DBUG_RETURN(true);
1029
2401
        }
1030
2402
      }
1031
2403
      cols2.rewind();
1032
 
 
1033
 
      if (create_proto.field_size() > 0)
1034
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1035
 
 
1036
2404
      {
1037
 
        column->length*= sql_field->charset->mbmaxlen;
 
2405
        column->length*= sql_field->charset->mbmaxlen;
1038
2406
 
1039
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1040
 
        {
1041
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1042
 
          {
1043
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1044
 
            return true;
1045
 
          }
1046
 
          if (! column->length)
1047
 
          {
1048
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
1049
 
            return true;
1050
 
          }
1051
 
        }
1052
 
        if (! (sql_field->flags & NOT_NULL_FLAG))
1053
 
        {
1054
 
          if (key->type == Key::PRIMARY)
1055
 
          {
1056
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1057
 
            sql_field->flags|= NOT_NULL_FLAG;
 
2407
        if (f_is_blob(sql_field->pack_flag))
 
2408
        {
 
2409
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
2410
          {
 
2411
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
2412
            DBUG_RETURN(true);
 
2413
          }
 
2414
          if (!column->length)
 
2415
          {
 
2416
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
2417
            DBUG_RETURN(true);
 
2418
          }
 
2419
        }
 
2420
        if (!(sql_field->flags & NOT_NULL_FLAG))
 
2421
        {
 
2422
          if (key->type == Key::PRIMARY)
 
2423
          {
 
2424
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
2425
            sql_field->flags|= NOT_NULL_FLAG;
 
2426
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1058
2427
            null_fields--;
1059
 
 
1060
 
            if (protofield)
1061
 
            {
1062
 
              message::Table::Field::FieldConstraints *constraints;
1063
 
              constraints= protofield->mutable_constraints();
1064
 
              constraints->set_is_nullable(false);
1065
 
            }
1066
 
 
1067
 
          }
1068
 
          else
 
2428
          }
 
2429
          else
1069
2430
          {
1070
2431
            key_info->flags|= HA_NULL_PART_KEY;
1071
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
2432
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1072
2433
            {
1073
2434
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1074
 
              return true;
 
2435
              DBUG_RETURN(true);
1075
2436
            }
1076
2437
          }
1077
 
        }
1078
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1079
 
        {
1080
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1081
 
            auto_increment--;                   // Field is used
1082
 
        }
 
2438
        }
 
2439
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
2440
        {
 
2441
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
 
2442
            auto_increment--;                   // Field is used
 
2443
        }
1083
2444
      }
1084
2445
 
1085
2446
      key_part_info->fieldnr= field;
1086
 
      key_part_info->offset=  (uint16_t) sql_field->offset;
1087
 
      key_part_info->key_type= 0;
 
2447
      key_part_info->offset=  (uint16) sql_field->offset;
 
2448
      key_part_info->key_type=sql_field->pack_flag;
1088
2449
      length= sql_field->key_length;
1089
2450
 
1090
2451
      if (column->length)
1091
2452
      {
1092
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
2453
        if (f_is_blob(sql_field->pack_flag))
1093
2454
        {
1094
2455
          if ((length=column->length) > max_key_length ||
1095
 
              length > engine->max_key_part_length())
 
2456
              length > file->max_key_part_length())
1096
2457
          {
1097
 
            length= min(max_key_length, engine->max_key_part_length());
 
2458
            length=min(max_key_length, file->max_key_part_length());
1098
2459
            if (key->type == Key::MULTIPLE)
1099
2460
            {
1100
2461
              /* not a critical problem */
1101
 
              char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2462
              char warn_buff[MYSQL_ERRMSG_SIZE];
1102
2463
              snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1103
2464
                       length);
1104
 
              push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2465
              push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1105
2466
                           ER_TOO_LONG_KEY, warn_buff);
1106
2467
              /* Align key length to multibyte char boundary */
1107
2468
              length-= length % sql_field->charset->mbmaxlen;
1109
2470
            else
1110
2471
            {
1111
2472
              my_error(ER_TOO_LONG_KEY,MYF(0),length);
1112
 
              return(true);
 
2473
              DBUG_RETURN(true);
1113
2474
            }
1114
2475
          }
1115
2476
        }
1116
2477
        else if ((column->length > length ||
1117
 
            ! Field::type_can_have_key_part(sql_field->sql_type)))
 
2478
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
 
2479
                   ((f_is_packed(sql_field->pack_flag) ||
 
2480
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
 
2481
                      (key_info->flags & HA_NOSAME))) &&
 
2482
                    column->length != length)))
1118
2483
        {
1119
2484
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1120
 
          return(true);
 
2485
          DBUG_RETURN(true);
1121
2486
        }
1122
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1123
 
        {
 
2487
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1124
2488
          length=column->length;
1125
 
        }
1126
2489
      }
1127
2490
      else if (length == 0)
1128
2491
      {
1129
2492
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1130
 
          return(true);
 
2493
          DBUG_RETURN(true);
1131
2494
      }
1132
 
      if (length > engine->max_key_part_length())
 
2495
      if (length > file->max_key_part_length())
1133
2496
      {
1134
 
        length= engine->max_key_part_length();
 
2497
        length= file->max_key_part_length();
1135
2498
        if (key->type == Key::MULTIPLE)
1136
2499
        {
1137
2500
          /* not a critical problem */
1138
 
          char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2501
          char warn_buff[MYSQL_ERRMSG_SIZE];
1139
2502
          snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1140
2503
                   length);
1141
 
          push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2504
          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1142
2505
                       ER_TOO_LONG_KEY, warn_buff);
1143
2506
          /* Align key length to multibyte char boundary */
1144
2507
          length-= length % sql_field->charset->mbmaxlen;
1146
2509
        else
1147
2510
        {
1148
2511
          my_error(ER_TOO_LONG_KEY,MYF(0),length);
1149
 
          return(true);
 
2512
          DBUG_RETURN(true);
1150
2513
        }
1151
2514
      }
1152
 
      key_part_info->length=(uint16_t) length;
 
2515
      key_part_info->length=(uint16) length;
1153
2516
      /* Use packed keys for long strings on the first column */
1154
2517
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1155
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1156
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1157
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
2518
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
2519
           (sql_field->sql_type == MYSQL_TYPE_STRING ||
 
2520
            sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
 
2521
            sql_field->pack_flag & FIELDFLAG_BLOB)))
1158
2522
      {
1159
 
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1160
 
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1161
 
        {
1162
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1163
 
        }
1164
 
        else
1165
 
        {
1166
 
          key_info->flags|= HA_PACK_KEY;
1167
 
        }
 
2523
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
 
2524
            sql_field->sql_type == MYSQL_TYPE_VARCHAR)
 
2525
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
2526
        else
 
2527
          key_info->flags|= HA_PACK_KEY;
1168
2528
      }
1169
2529
      /* Check if the key segment is partial, set the key flag accordingly */
1170
2530
      if (length != sql_field->key_length)
1182
2542
          {
1183
2543
            my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
1184
2544
                       MYF(0));
1185
 
            return(true);
 
2545
            DBUG_RETURN(true);
1186
2546
          }
1187
 
          static const char pkey_name[]= "PRIMARY";
1188
 
          key_name=pkey_name;
 
2547
          key_name=primary_key_name;
1189
2548
          primary_key=1;
1190
2549
        }
1191
2550
        else if (!(key_name= key->name.str))
1194
2553
        if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
1195
2554
        {
1196
2555
          my_error(ER_DUP_KEYNAME, MYF(0), key_name);
1197
 
          return(true);
 
2556
          DBUG_RETURN(true);
1198
2557
        }
1199
2558
        key_info->name=(char*) key_name;
1200
2559
      }
1202
2561
    if (!key_info->name || check_column_name(key_info->name))
1203
2562
    {
1204
2563
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1205
 
      return(true);
 
2564
      DBUG_RETURN(true);
1206
2565
    }
1207
2566
    if (!(key_info->flags & HA_NULL_PART_KEY))
1208
2567
      unique_key=1;
1209
 
    key_info->key_length=(uint16_t) key_length;
 
2568
    key_info->key_length=(uint16) key_length;
1210
2569
    if (key_length > max_key_length)
1211
2570
    {
1212
2571
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1213
 
      return(true);
 
2572
      DBUG_RETURN(true);
1214
2573
    }
1215
2574
    key_info++;
1216
2575
  }
1217
2576
  if (!unique_key && !primary_key &&
1218
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
2577
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1219
2578
  {
1220
2579
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1221
 
    return(true);
 
2580
    DBUG_RETURN(true);
1222
2581
  }
1223
2582
  if (auto_increment > 0)
1224
2583
  {
1225
2584
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1226
 
    return(true);
 
2585
    DBUG_RETURN(true);
1227
2586
  }
1228
2587
  /* Sort keys in optimized order */
1229
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1230
 
                     (qsort_cmp) sort_keys);
 
2588
  my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
 
2589
           (qsort_cmp) sort_keys);
 
2590
  create_info->null_bits= null_fields;
1231
2591
 
1232
2592
  /* Check fields. */
1233
2593
  it.rewind();
1235
2595
  {
1236
2596
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1237
2597
 
1238
 
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
 
2598
    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1239
2599
        !sql_field->def &&
1240
 
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
 
2600
        sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1241
2601
        (sql_field->flags & NOT_NULL_FLAG) &&
1242
2602
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1243
2603
    {
1256
2616
      */
1257
2617
 
1258
2618
      my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
1259
 
      return(true);
 
2619
      DBUG_RETURN(true);
1260
2620
    }
1261
2621
  }
1262
2622
 
1263
 
  return(false);
1264
 
}
 
2623
  DBUG_RETURN(false);
 
2624
}
 
2625
 
 
2626
 
 
2627
/*
 
2628
  Set table default charset, if not set
 
2629
 
 
2630
  SYNOPSIS
 
2631
    set_table_default_charset()
 
2632
    create_info        Table create information
 
2633
 
 
2634
  DESCRIPTION
 
2635
    If the table character set was not given explicitely,
 
2636
    let's fetch the database default character set and
 
2637
    apply it to the table.
 
2638
*/
 
2639
 
 
2640
static void set_table_default_charset(THD *thd,
 
2641
                                      HA_CREATE_INFO *create_info, char *db)
 
2642
{
 
2643
  /*
 
2644
    If the table character set was not given explicitly,
 
2645
    let's fetch the database default character set and
 
2646
    apply it to the table.
 
2647
  */
 
2648
  if (!create_info->default_table_charset)
 
2649
  {
 
2650
    HA_CREATE_INFO db_info;
 
2651
 
 
2652
    load_db_opt_by_name(thd, db, &db_info);
 
2653
 
 
2654
    create_info->default_table_charset= db_info.default_table_charset;
 
2655
  }
 
2656
}
 
2657
 
1265
2658
 
1266
2659
/*
1267
2660
  Extend long VARCHAR fields to blob & prepare field if it's a blob
1276
2669
        In this case the error is given
1277
2670
*/
1278
2671
 
1279
 
static bool prepare_blob_field(Session *,
1280
 
                               CreateField *sql_field)
 
2672
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
1281
2673
{
 
2674
  DBUG_ENTER("prepare_blob_field");
1282
2675
 
1283
2676
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
1284
2677
      !(sql_field->flags & BLOB_FLAG))
1285
2678
  {
1286
2679
    my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1287
2680
             MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1288
 
    return 1;
 
2681
    DBUG_RETURN(1);
1289
2682
  }
1290
 
 
 
2683
    
1291
2684
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1292
2685
  {
1293
 
    if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
2686
    if (sql_field->sql_type == MYSQL_TYPE_BLOB)
1294
2687
    {
1295
2688
      /* The user has given a length to the blob column */
 
2689
      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1296
2690
      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1297
2691
    }
1298
2692
    sql_field->length= 0;
1299
2693
  }
1300
 
  return 0;
 
2694
  DBUG_RETURN(0);
1301
2695
}
1302
2696
 
1303
 
static bool locked_create_event(Session *session,
1304
 
                                TableIdentifier &identifier,
1305
 
                                HA_CREATE_INFO *create_info,
1306
 
                                message::Table &table_proto,
1307
 
                                AlterInfo *alter_info,
1308
 
                                bool is_if_not_exists,
1309
 
                                bool internal_tmp_table,
1310
 
                                uint db_options,
1311
 
                                uint key_count,
1312
 
                                KeyInfo *key_info_buffer)
 
2697
 
 
2698
/*
 
2699
  Preparation of Create_field for SP function return values.
 
2700
  Based on code used in the inner loop of mysql_prepare_create_table()
 
2701
  above.
 
2702
 
 
2703
  SYNOPSIS
 
2704
    sp_prepare_create_field()
 
2705
    thd                 Thread object
 
2706
    sql_field           Field to prepare
 
2707
 
 
2708
  DESCRIPTION
 
2709
    Prepares the field structures for field creation.
 
2710
 
 
2711
*/
 
2712
 
 
2713
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
1313
2714
{
1314
 
  bool error= true;
1315
 
 
1316
 
  {
1317
 
 
1318
 
    /*
1319
 
      @note if we are building a temp table we need to check to see if a temp table
1320
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1321
 
      to create a table under a temporary table.
1322
 
    */
1323
 
    bool exists= 
1324
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1325
 
                                            identifier.getType() != message::Table::STANDARD );
1326
 
 
1327
 
    if (exists)
1328
 
    {
1329
 
      if (is_if_not_exists)
1330
 
      {
1331
 
        error= false;
1332
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1333
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1334
 
                            identifier.getTableName().c_str());
1335
 
        create_info->table_existed= 1;          // Mark that table existed
1336
 
        return error;
1337
 
      }
1338
 
 
1339
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1340
 
      return error;
1341
 
    }
1342
 
 
1343
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1344
 
    {
1345
 
      /*
1346
 
        We don't assert here, but check the result, because the table could be
1347
 
        in the table definition cache and in the same time the .frm could be
1348
 
        missing from the disk, in case of manual intervention which deletes
1349
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1350
 
        Then she could create the table. This case is pretty obscure and
1351
 
        therefore we don't introduce a new error message only for it.
1352
 
      */
1353
 
      /*
1354
 
        @todo improve this error condition.
1355
 
      */
1356
 
      if (TableShare::getShare(identifier))
1357
 
      {
1358
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1359
 
        return error;
1360
 
      }
1361
 
    }
1362
 
  }
1363
 
 
1364
 
  session->set_proc_info("creating table");
1365
 
  create_info->table_existed= 0;                // Mark that table is created
1366
 
 
1367
 
  create_info->table_options= db_options;
1368
 
 
1369
 
  if (not rea_create_table(session, identifier,
1370
 
                           table_proto,
1371
 
                           create_info, alter_info->create_list,
1372
 
                           key_count, key_info_buffer))
1373
 
  {
1374
 
    return error;
1375
 
  }
1376
 
 
1377
 
  if (identifier.getType() == message::Table::TEMPORARY)
1378
 
  {
1379
 
    /* Open table and put in temporary table list */
1380
 
    if (not (session->open_temporary_table(identifier)))
1381
 
    {
1382
 
      (void) session->rm_temporary_table(identifier);
1383
 
      return error;
1384
 
    }
1385
 
  }
1386
 
 
1387
 
  /* 
1388
 
    We keep this behind the lock to make sure ordering is correct for a table.
1389
 
    This is a very unlikely problem where before we would write out to the
1390
 
    trans log, someone would do a delete/create operation.
1391
 
  */
1392
 
 
1393
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1394
 
  {
1395
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1396
 
    transaction_services.createTable(session, table_proto);
1397
 
  }
1398
 
 
1399
 
  return false;
 
2715
  if (sql_field->sql_type == MYSQL_TYPE_SET ||
 
2716
      sql_field->sql_type == MYSQL_TYPE_ENUM)
 
2717
  {
 
2718
    uint32 field_length, dummy;
 
2719
    if (sql_field->sql_type == MYSQL_TYPE_SET)
 
2720
    {
 
2721
      calculate_interval_lengths(sql_field->charset,
 
2722
                                 sql_field->interval, &dummy, 
 
2723
                                 &field_length);
 
2724
      sql_field->length= field_length + 
 
2725
                         (sql_field->interval->count - 1);
 
2726
    }
 
2727
    else /* MYSQL_TYPE_ENUM */
 
2728
    {
 
2729
      calculate_interval_lengths(sql_field->charset,
 
2730
                                 sql_field->interval,
 
2731
                                 &field_length, &dummy);
 
2732
      sql_field->length= field_length;
 
2733
    }
 
2734
    set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
 
2735
  }
 
2736
 
 
2737
  sql_field->create_length_to_internal_length();
 
2738
  DBUG_ASSERT(sql_field->def == 0);
 
2739
  /* Can't go wrong as sql_field->def is not defined */
 
2740
  (void) prepare_blob_field(thd, sql_field);
1400
2741
}
1401
2742
 
1402
2743
 
1403
2744
/*
1404
 
  Ignore the name of this function... it locks :(
1405
 
 
1406
2745
  Create a table
1407
2746
 
1408
2747
  SYNOPSIS
1409
2748
    mysql_create_table_no_lock()
1410
 
    session                     Thread object
 
2749
    thd                 Thread object
1411
2750
    db                  Database
1412
2751
    table_name          Table name
1413
2752
    create_info         Create information (like MAX_ROWS)
1414
2753
    fields              List of fields to create
1415
2754
    keys                List of keys to create
1416
2755
    internal_tmp_table  Set to 1 if this is an internal temporary table
1417
 
                        (From ALTER Table)
1418
 
    select_field_count
 
2756
                        (From ALTER TABLE)
 
2757
    select_field_count  
1419
2758
 
1420
2759
  DESCRIPTION
1421
2760
    If one creates a temporary table, this is automatically opened
1425
2764
    that concurrent operations won't intervene. mysql_create_table()
1426
2765
    is a wrapper that can be used for this.
1427
2766
 
 
2767
    no_log is needed for the case of CREATE ... SELECT,
 
2768
    as the logging will be done later in sql_insert.cc
 
2769
    select_field_count is also used for CREATE ... SELECT,
 
2770
    and must be zero for standard create of table.
 
2771
 
1428
2772
  RETURN VALUES
1429
2773
    false OK
1430
2774
    true  error
1431
2775
*/
1432
2776
 
1433
 
bool mysql_create_table_no_lock(Session *session,
1434
 
                                TableIdentifier &identifier,
 
2777
bool mysql_create_table_no_lock(THD *thd,
 
2778
                                const char *db, const char *table_name,
1435
2779
                                HA_CREATE_INFO *create_info,
1436
 
                                message::Table &table_proto,
1437
 
                                AlterInfo *alter_info,
 
2780
                                Alter_info *alter_info,
1438
2781
                                bool internal_tmp_table,
1439
 
                                uint32_t select_field_count,
1440
 
                                bool is_if_not_exists)
 
2782
                                uint select_field_count)
1441
2783
{
 
2784
  char          path[FN_REFLEN];
 
2785
  uint          path_length;
 
2786
  const char    *alias;
1442
2787
  uint          db_options, key_count;
1443
 
  KeyInfo               *key_info_buffer;
 
2788
  KEY           *key_info_buffer;
 
2789
  handler       *file;
1444
2790
  bool          error= true;
 
2791
  DBUG_ENTER("mysql_create_table_no_lock");
 
2792
  DBUG_PRINT("enter", ("db: '%s'  table: '%s'  tmp: %d",
 
2793
                       db, table_name, internal_tmp_table));
1445
2794
 
 
2795
 
1446
2796
  /* Check for duplicate fields and check type of table to create */
1447
 
  if (not alter_info->create_list.elements)
 
2797
  if (!alter_info->create_list.elements)
1448
2798
  {
1449
2799
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1450
2800
               MYF(0));
1451
 
    return true;
 
2801
    DBUG_RETURN(true);
1452
2802
  }
1453
 
  assert(identifier.getTableName() == table_proto.name());
 
2803
  if (check_engine(thd, table_name, create_info))
 
2804
    DBUG_RETURN(true);
1454
2805
  db_options= create_info->table_options;
1455
 
 
1456
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1457
 
 
1458
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1459
 
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
2806
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
2807
    db_options|=HA_OPTION_PACK_RECORD;
 
2808
  alias= table_case_name(create_info, table_name);
 
2809
  if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
 
2810
                              create_info->db_type)))
 
2811
  {
 
2812
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
2813
    DBUG_RETURN(true);
 
2814
  }
 
2815
 
 
2816
  set_table_default_charset(thd, create_info, (char*) db);
 
2817
 
 
2818
  if (mysql_prepare_create_table(thd, create_info, alter_info,
1460
2819
                                 internal_tmp_table,
1461
 
                                 &db_options,
1462
 
                                 &key_info_buffer, &key_count,
1463
 
                                 select_field_count))
1464
 
  {
1465
 
    boost::mutex::scoped_lock lock(LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1466
 
    error= locked_create_event(session,
1467
 
                               identifier,
1468
 
                               create_info,
1469
 
                               table_proto,
1470
 
                               alter_info,
1471
 
                               is_if_not_exists,
1472
 
                               internal_tmp_table,
1473
 
                               db_options, key_count,
1474
 
                               key_info_buffer);
1475
 
  }
1476
 
 
1477
 
  session->set_proc_info("After create");
1478
 
 
1479
 
  return(error);
1480
 
}
1481
 
 
1482
 
/**
1483
 
  @note the following two methods implement create [temporary] table.
1484
 
*/
1485
 
static bool drizzle_create_table(Session *session,
1486
 
                                 TableIdentifier &identifier,
1487
 
                                 HA_CREATE_INFO *create_info,
1488
 
                                 message::Table &table_proto,
1489
 
                                 AlterInfo *alter_info,
1490
 
                                 bool internal_tmp_table,
1491
 
                                 uint32_t select_field_count,
1492
 
                                 bool is_if_not_exists)
1493
 
{
1494
 
  Table *name_lock= NULL;
1495
 
  bool result;
1496
 
 
1497
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1498
 
  {
1499
 
    result= true;
1500
 
  }
1501
 
  else if (name_lock == NULL)
1502
 
  {
1503
 
    if (is_if_not_exists)
1504
 
    {
1505
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2820
                                 &db_options, file,
 
2821
                          &key_info_buffer, &key_count,
 
2822
                          select_field_count))
 
2823
    goto err;
 
2824
 
 
2825
      /* Check if table exists */
 
2826
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2827
  {
 
2828
    path_length= build_tmptable_filename(thd, path, sizeof(path));
 
2829
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
2830
  }
 
2831
  else  
 
2832
  {
 
2833
 #ifdef FN_DEVCHAR
 
2834
    /* check if the table name contains FN_DEVCHAR when defined */
 
2835
    if (strchr(alias, FN_DEVCHAR))
 
2836
    {
 
2837
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
 
2838
      DBUG_RETURN(true);
 
2839
    }
 
2840
#endif
 
2841
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
2842
                                      internal_tmp_table ? FN_IS_TMP : 0);
 
2843
  }
 
2844
 
 
2845
  /* Check if table already exists */
 
2846
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
2847
      find_temporary_table(thd, db, table_name))
 
2848
  {
 
2849
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2850
    {
 
2851
      create_info->table_existed= 1;            // Mark that table existed
 
2852
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1506
2853
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1507
 
                          identifier.getTableName().c_str());
1508
 
      create_info->table_existed= 1;
1509
 
      result= false;
1510
 
    }
1511
 
    else
1512
 
    {
1513
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1514
 
      result= true;
1515
 
    }
1516
 
  }
1517
 
  else
1518
 
  {
1519
 
    result= mysql_create_table_no_lock(session,
1520
 
                                       identifier,
1521
 
                                       create_info,
1522
 
                                       table_proto,
1523
 
                                       alter_info,
1524
 
                                       internal_tmp_table,
1525
 
                                       select_field_count,
1526
 
                                       is_if_not_exists);
1527
 
  }
1528
 
 
1529
 
  if (name_lock)
1530
 
  {
1531
 
    boost::mutex::scoped_lock lock(LOCK_open); /* Lock for removing name_lock during table create */
1532
 
    session->unlink_open_table(name_lock);
1533
 
  }
1534
 
 
1535
 
  return(result);
 
2854
                          alias);
 
2855
      error= 0;
 
2856
      goto err;
 
2857
    }
 
2858
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
 
2859
    goto err;
 
2860
  }
 
2861
 
 
2862
  VOID(pthread_mutex_lock(&LOCK_open));
 
2863
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2864
  {
 
2865
    if (!access(path,F_OK))
 
2866
    {
 
2867
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2868
        goto warn;
 
2869
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
2870
      goto unlock_and_end;
 
2871
    }
 
2872
    /*
 
2873
      We don't assert here, but check the result, because the table could be
 
2874
      in the table definition cache and in the same time the .frm could be
 
2875
      missing from the disk, in case of manual intervention which deletes
 
2876
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
2877
      Then she could create the table. This case is pretty obscure and
 
2878
      therefore we don't introduce a new error message only for it.
 
2879
    */
 
2880
    if (get_cached_table_share(db, alias))
 
2881
    {
 
2882
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2883
      goto unlock_and_end;
 
2884
    }
 
2885
  }
 
2886
 
 
2887
  /*
 
2888
    Check that table with given name does not already
 
2889
    exist in any storage engine. In such a case it should
 
2890
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
2891
    unless user specified CREATE TABLE IF EXISTS
 
2892
    The LOCK_open mutex has been locked to make sure no
 
2893
    one else is attempting to discover the table. Since
 
2894
    it's not on disk as a frm file, no one could be using it!
 
2895
  */
 
2896
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2897
  {
 
2898
    bool create_if_not_exists =
 
2899
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
2900
    int retcode = ha_table_exists_in_engine(thd, db, table_name);
 
2901
    DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
 
2902
    switch (retcode)
 
2903
    {
 
2904
      case HA_ERR_NO_SUCH_TABLE:
 
2905
        /* Normal case, no table exists. we can go and create it */
 
2906
        break;
 
2907
      case HA_ERR_TABLE_EXIST:
 
2908
        DBUG_PRINT("info", ("Table existed in handler"));
 
2909
 
 
2910
      if (create_if_not_exists)
 
2911
        goto warn;
 
2912
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
2913
      goto unlock_and_end;
 
2914
        break;
 
2915
      default:
 
2916
        DBUG_PRINT("info", ("error: %u from storage engine", retcode));
 
2917
        my_error(retcode, MYF(0),table_name);
 
2918
        goto unlock_and_end;
 
2919
    }
 
2920
  }
 
2921
 
 
2922
  thd_proc_info(thd, "creating table");
 
2923
  create_info->table_existed= 0;                // Mark that table is created
 
2924
 
 
2925
#ifdef HAVE_READLINK
 
2926
  if (test_if_data_home_dir(create_info->data_file_name))
 
2927
  {
 
2928
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
 
2929
    goto unlock_and_end;
 
2930
  }
 
2931
  if (test_if_data_home_dir(create_info->index_file_name))
 
2932
  {
 
2933
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
 
2934
    goto unlock_and_end;
 
2935
  }
 
2936
 
 
2937
  if (!my_use_symdir)
 
2938
#endif /* HAVE_READLINK */
 
2939
  {
 
2940
    if (create_info->data_file_name)
 
2941
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
 
2942
                   "DATA DIRECTORY option ignored");
 
2943
    if (create_info->index_file_name)
 
2944
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
 
2945
                   "INDEX DIRECTORY option ignored");
 
2946
    create_info->data_file_name= create_info->index_file_name= 0;
 
2947
  }
 
2948
  create_info->table_options=db_options;
 
2949
 
 
2950
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
 
2951
  if (rea_create_table(thd, path, db, table_name,
 
2952
                       create_info, alter_info->create_list,
 
2953
                       key_count, key_info_buffer, file))
 
2954
    goto unlock_and_end;
 
2955
 
 
2956
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2957
  {
 
2958
    /* Open table and put in temporary table list */
 
2959
    if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
 
2960
    {
 
2961
      (void) rm_temporary_table(create_info->db_type, path, false);
 
2962
      goto unlock_and_end;
 
2963
    }
 
2964
    thd->thread_specific_used= true;
 
2965
  }
 
2966
 
 
2967
  /*
 
2968
    Don't write statement if:
 
2969
    - It is an internal temporary table,
 
2970
    - Row-based logging is used and it we are creating a temporary table, or
 
2971
    - The binary log is not open.
 
2972
    Otherwise, the statement shall be binlogged.
 
2973
   */
 
2974
  if (!internal_tmp_table &&
 
2975
      (!thd->current_stmt_binlog_row_based ||
 
2976
       (thd->current_stmt_binlog_row_based &&
 
2977
        !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
2978
    write_bin_log(thd, true, thd->query, thd->query_length);
 
2979
  error= false;
 
2980
unlock_and_end:
 
2981
  VOID(pthread_mutex_unlock(&LOCK_open));
 
2982
 
 
2983
err:
 
2984
  thd_proc_info(thd, "After create");
 
2985
  delete file;
 
2986
  DBUG_RETURN(error);
 
2987
 
 
2988
warn:
 
2989
  error= false;
 
2990
  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
2991
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
2992
                      alias);
 
2993
  create_info->table_existed= 1;                // Mark that table existed
 
2994
  goto unlock_and_end;
1536
2995
}
1537
2996
 
1538
2997
 
1539
2998
/*
1540
2999
  Database locking aware wrapper for mysql_create_table_no_lock(),
1541
3000
*/
1542
 
bool mysql_create_table(Session *session,
1543
 
                        TableIdentifier &identifier,
 
3001
 
 
3002
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
1544
3003
                        HA_CREATE_INFO *create_info,
1545
 
                        message::Table &table_proto,
1546
 
                        AlterInfo *alter_info,
 
3004
                        Alter_info *alter_info,
1547
3005
                        bool internal_tmp_table,
1548
 
                        uint32_t select_field_count,
1549
 
                        bool is_if_not_exists)
 
3006
                        uint select_field_count)
1550
3007
{
1551
 
  if (identifier.isTmp())
1552
 
  {
1553
 
    return mysql_create_table_no_lock(session,
1554
 
                                      identifier,
1555
 
                                      create_info,
1556
 
                                      table_proto,
1557
 
                                      alter_info,
1558
 
                                      internal_tmp_table,
1559
 
                                      select_field_count,
1560
 
                                      is_if_not_exists);
1561
 
  }
1562
 
 
1563
 
  return drizzle_create_table(session,
1564
 
                              identifier,
1565
 
                              create_info,
1566
 
                              table_proto,
1567
 
                              alter_info,
1568
 
                              internal_tmp_table,
1569
 
                              select_field_count,
1570
 
                              is_if_not_exists);
 
3008
  TABLE *name_lock= 0;
 
3009
  bool result;
 
3010
  DBUG_ENTER("mysql_create_table");
 
3011
 
 
3012
  /* Wait for any database locks */
 
3013
  pthread_mutex_lock(&LOCK_lock_db);
 
3014
  while (!thd->killed &&
 
3015
         hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
 
3016
  {
 
3017
    wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
 
3018
    pthread_mutex_lock(&LOCK_lock_db);
 
3019
  }
 
3020
 
 
3021
  if (thd->killed)
 
3022
  {
 
3023
    pthread_mutex_unlock(&LOCK_lock_db);
 
3024
    DBUG_RETURN(true);
 
3025
  }
 
3026
  creating_table++;
 
3027
  pthread_mutex_unlock(&LOCK_lock_db);
 
3028
 
 
3029
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
3030
  {
 
3031
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
3032
    {
 
3033
      result= true;
 
3034
      goto unlock;
 
3035
    }
 
3036
    if (!name_lock)
 
3037
    {
 
3038
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
3039
      {
 
3040
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
3041
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
3042
                            table_name);
 
3043
        create_info->table_existed= 1;
 
3044
        result= false;
 
3045
      }
 
3046
      else
 
3047
      {
 
3048
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
3049
        result= true;
 
3050
      }
 
3051
      goto unlock;
 
3052
    }
 
3053
  }
 
3054
 
 
3055
  result= mysql_create_table_no_lock(thd, db, table_name, create_info,
 
3056
                                     alter_info,
 
3057
                                     internal_tmp_table,
 
3058
                                     select_field_count);
 
3059
 
 
3060
unlock:
 
3061
  if (name_lock)
 
3062
  {
 
3063
    pthread_mutex_lock(&LOCK_open);
 
3064
    unlink_open_table(thd, name_lock, false);
 
3065
    pthread_mutex_unlock(&LOCK_open);
 
3066
  }
 
3067
  pthread_mutex_lock(&LOCK_lock_db);
 
3068
  if (!--creating_table && creating_database)
 
3069
    pthread_cond_signal(&COND_refresh);
 
3070
  pthread_mutex_unlock(&LOCK_lock_db);
 
3071
  DBUG_RETURN(result);
1571
3072
}
1572
3073
 
1573
3074
 
1576
3077
**/
1577
3078
 
1578
3079
static bool
1579
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
3080
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1580
3081
{
1581
 
  for (KeyInfo *key=start ; key != end ; key++)
 
3082
  for (KEY *key=start ; key != end ; key++)
1582
3083
    if (!my_strcasecmp(system_charset_info,name,key->name))
1583
3084
      return 1;
1584
3085
  return 0;
1586
3087
 
1587
3088
 
1588
3089
static char *
1589
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
3090
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1590
3091
{
1591
3092
  char buff[MAX_FIELD_NAME],*buff_end;
1592
3093
 
1593
3094
  if (!check_if_keyname_exists(field_name,start,end) &&
1594
 
      !is_primary_key_name(field_name))
 
3095
      my_strcasecmp(system_charset_info,field_name,primary_key_name))
1595
3096
    return (char*) field_name;                  // Use fieldname
1596
 
 
1597
 
  buff_end= strncpy(buff, field_name, sizeof(buff)-4);
1598
 
  buff_end+= strlen(buff);
 
3097
  buff_end=strmake(buff,field_name, sizeof(buff)-4);
1599
3098
 
1600
3099
  /*
1601
3100
    Only 3 chars + '\0' left, so need to limit to 2 digit
1602
3101
    This is ok as we can't have more than 100 keys anyway
1603
3102
  */
1604
 
  for (uint32_t i=2 ; i< 100; i++)
 
3103
  for (uint i=2 ; i< 100; i++)
1605
3104
  {
1606
3105
    *buff_end= '_';
1607
 
    internal::int10_to_str(i, buff_end+1, 10);
 
3106
    int10_to_str(i, buff_end+1, 10);
1608
3107
    if (!check_if_keyname_exists(buff,start,end))
1609
 
      return memory::sql_strdup(buff);
 
3108
      return sql_strdup(buff);
1610
3109
  }
1611
3110
  return (char*) "not_specified";               // Should never happen
1612
3111
}
1616
3115
** Alter a table definition
1617
3116
****************************************************************************/
1618
3117
 
 
3118
 
1619
3119
/*
1620
3120
  Rename a table.
1621
3121
 
1622
3122
  SYNOPSIS
1623
3123
    mysql_rename_table()
1624
 
      session
1625
 
      base                      The plugin::StorageEngine handle.
 
3124
      base                      The handlerton handle.
1626
3125
      old_db                    The old database name.
1627
3126
      old_name                  The old table name.
1628
3127
      new_db                    The new database name.
1629
3128
      new_name                  The new table name.
 
3129
      flags                     flags for build_table_filename().
 
3130
                                FN_FROM_IS_TMP old_name is temporary.
 
3131
                                FN_TO_IS_TMP   new_name is temporary.
 
3132
                                NO_FRM_RENAME  Don't rename the FRM file
 
3133
                                but only the table in the storage engine.
1630
3134
 
1631
3135
  RETURN
1632
3136
    false   OK
1634
3138
*/
1635
3139
 
1636
3140
bool
1637
 
mysql_rename_table(Session &session,
1638
 
                   plugin::StorageEngine *base,
1639
 
                   TableIdentifier &from,
1640
 
                   TableIdentifier &to)
 
3141
mysql_rename_table(handlerton *base, const char *old_db,
 
3142
                   const char *old_name, const char *new_db,
 
3143
                   const char *new_name, uint flags)
1641
3144
{
1642
 
  int error= 0;
1643
 
 
1644
 
  assert(base);
1645
 
 
1646
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
1647
 
  {
1648
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1649
 
    return true;
1650
 
  }
1651
 
 
1652
 
  error= base->renameTable(session, from, to);
1653
 
 
 
3145
  THD *thd= current_thd;
 
3146
  char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
 
3147
  char *from_base= from, *to_base= to;
 
3148
  char tmp_name[NAME_LEN+1];
 
3149
  handler *file;
 
3150
  int error=0;
 
3151
  DBUG_ENTER("mysql_rename_table");
 
3152
  DBUG_PRINT("enter", ("old: '%s'.'%s'  new: '%s'.'%s'",
 
3153
                       old_db, old_name, new_db, new_name));
 
3154
 
 
3155
  file= (base == NULL ? 0 :
 
3156
         get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
 
3157
 
 
3158
  build_table_filename(from, sizeof(from), old_db, old_name, "",
 
3159
                       flags & FN_FROM_IS_TMP);
 
3160
  build_table_filename(to, sizeof(to), new_db, new_name, "",
 
3161
                       flags & FN_TO_IS_TMP);
 
3162
 
 
3163
  /*
 
3164
    If lower_case_table_names == 2 (case-preserving but case-insensitive
 
3165
    file system) and the storage is not HA_FILE_BASED, we need to provide
 
3166
    a lowercase file name, but we leave the .frm in mixed case.
 
3167
   */
 
3168
  if (lower_case_table_names == 2 && file &&
 
3169
      !(file->ha_table_flags() & HA_FILE_BASED))
 
3170
  {
 
3171
    strmov(tmp_name, old_name);
 
3172
    my_casedn_str(files_charset_info, tmp_name);
 
3173
    build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
 
3174
                         flags & FN_FROM_IS_TMP);
 
3175
    from_base= lc_from;
 
3176
 
 
3177
    strmov(tmp_name, new_name);
 
3178
    my_casedn_str(files_charset_info, tmp_name);
 
3179
    build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
 
3180
                         flags & FN_TO_IS_TMP);
 
3181
    to_base= lc_to;
 
3182
  }
 
3183
  if (!file || !(error=file->ha_rename_table(from_base, to_base)))
 
3184
  {
 
3185
    if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
 
3186
    {
 
3187
      error=my_errno;
 
3188
      /* Restore old file name */
 
3189
      if (file)
 
3190
        file->ha_rename_table(to_base, from_base);
 
3191
    }
 
3192
  }
 
3193
  delete file;
1654
3194
  if (error == HA_ERR_WRONG_COMMAND)
1655
 
  {
1656
 
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1657
 
  }
 
3195
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
1658
3196
  else if (error)
1659
 
  {
1660
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str();
1661
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str();
1662
 
 
1663
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1664
 
  }
1665
 
 
1666
 
  return error ? true : false; 
 
3197
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
3198
  DBUG_RETURN(error != 0);
1667
3199
}
1668
3200
 
1669
3201
 
1672
3204
 
1673
3205
  SYNOPSIS
1674
3206
    wait_while_table_is_used()
1675
 
    session                     Thread Cursor
 
3207
    thd                 Thread handler
1676
3208
    table               Table to remove from cache
1677
3209
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1678
3210
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1686
3218
    Win32 clients must also have a WRITE LOCK on the table !
1687
3219
*/
1688
3220
 
1689
 
void wait_while_table_is_used(Session *session, Table *table,
 
3221
void wait_while_table_is_used(THD *thd, TABLE *table,
1690
3222
                              enum ha_extra_function function)
1691
3223
{
1692
 
 
1693
 
  safe_mutex_assert_owner(LOCK_open.native_handle());
1694
 
 
1695
 
  table->cursor->extra(function);
 
3224
  DBUG_ENTER("wait_while_table_is_used");
 
3225
  DBUG_PRINT("enter", ("table: '%s'  share: 0x%lx  db_stat: %u  version: %lu",
 
3226
                       table->s->table_name.str, (ulong) table->s,
 
3227
                       table->db_stat, table->s->version));
 
3228
 
 
3229
  safe_mutex_assert_owner(&LOCK_open);
 
3230
 
 
3231
  VOID(table->file->extra(function));
1696
3232
  /* Mark all tables that are in use as 'old' */
1697
 
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
 
3233
  mysql_lock_abort(thd, table, true);   /* end threads waiting on lock */
1698
3234
 
1699
3235
  /* Wait until all there are no other threads that has this table open */
1700
 
  TableIdentifier identifier(table->getMutableShare()->getSchemaName(), table->getMutableShare()->getTableName());
1701
 
  remove_table_from_cache(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
3236
  remove_table_from_cache(thd, table->s->db.str,
 
3237
                          table->s->table_name.str,
 
3238
                          RTFC_WAIT_OTHER_THREAD_FLAG);
 
3239
  DBUG_VOID_RETURN;
1702
3240
}
1703
3241
 
1704
3242
/*
1706
3244
 
1707
3245
  SYNOPSIS
1708
3246
    close_cached_table()
1709
 
    session                     Thread Cursor
 
3247
    thd                 Thread handler
1710
3248
    table               Table to remove from cache
1711
3249
 
1712
3250
  NOTES
1718
3256
    Win32 clients must also have a WRITE LOCK on the table !
1719
3257
*/
1720
3258
 
1721
 
void Session::close_cached_table(Table *table)
 
3259
void close_cached_table(THD *thd, TABLE *table)
1722
3260
{
 
3261
  DBUG_ENTER("close_cached_table");
1723
3262
 
1724
 
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
 
3263
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
1725
3264
  /* Close lock if this is not got with LOCK TABLES */
1726
 
  if (lock)
 
3265
  if (thd->lock)
1727
3266
  {
1728
 
    mysql_unlock_tables(this, lock);
1729
 
    lock= NULL;                 // Start locked threads
 
3267
    mysql_unlock_tables(thd, thd->lock);
 
3268
    thd->lock=0;                        // Start locked threads
1730
3269
  }
1731
3270
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1732
 
  unlink_open_table(table);
 
3271
  unlink_open_table(thd, table, true);
1733
3272
 
1734
3273
  /* When lock on LOCK_open is freed other threads can continue */
1735
3274
  broadcast_refresh();
1736
 
}
 
3275
  DBUG_VOID_RETURN;
 
3276
}
 
3277
 
 
3278
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
 
3279
                             const char* operator_name, const char* errmsg)
 
3280
 
 
3281
{
 
3282
  Protocol *protocol= thd->protocol;
 
3283
  protocol->prepare_for_resend();
 
3284
  protocol->store(table->alias, system_charset_info);
 
3285
  protocol->store((char*) operator_name, system_charset_info);
 
3286
  protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3287
  protocol->store(errmsg, system_charset_info);
 
3288
  thd->clear_error();
 
3289
  if (protocol->write())
 
3290
    return -1;
 
3291
  return 1;
 
3292
}
 
3293
 
 
3294
 
 
3295
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
 
3296
                              HA_CHECK_OPT *check_opt)
 
3297
{
 
3298
  int error= 0;
 
3299
  TABLE tmp_table, *table;
 
3300
  TABLE_SHARE *share;
 
3301
  char from[FN_REFLEN],tmp[FN_REFLEN+32];
 
3302
  const char **ext;
 
3303
  struct stat stat_info;
 
3304
  DBUG_ENTER("prepare_for_repair");
 
3305
 
 
3306
  if (!(check_opt->sql_flags & TT_USEFRM))
 
3307
    DBUG_RETURN(0);
 
3308
 
 
3309
  if (!(table= table_list->table))              /* if open_ltable failed */
 
3310
  {
 
3311
    char key[MAX_DBKEY_LENGTH];
 
3312
    uint key_length;
 
3313
 
 
3314
    key_length= create_table_def_key(thd, key, table_list, 0);
 
3315
    pthread_mutex_lock(&LOCK_open);
 
3316
    if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
 
3317
                                  &error))))
 
3318
    {
 
3319
      pthread_mutex_unlock(&LOCK_open);
 
3320
      DBUG_RETURN(0);                           // Can't open frm file
 
3321
    }
 
3322
 
 
3323
    if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
 
3324
    {
 
3325
      release_table_share(share, RELEASE_NORMAL);
 
3326
      pthread_mutex_unlock(&LOCK_open);
 
3327
      DBUG_RETURN(0);                           // Out of memory
 
3328
    }
 
3329
    table= &tmp_table;
 
3330
    pthread_mutex_unlock(&LOCK_open);
 
3331
  }
 
3332
 
 
3333
  /*
 
3334
    REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
 
3335
  */
 
3336
  if (table->s->tmp_table)
 
3337
  {
 
3338
    error= send_check_errmsg(thd, table_list, "repair",
 
3339
                             "Cannot repair temporary table from .frm file");
 
3340
    goto end;
 
3341
  }
 
3342
 
 
3343
  /*
 
3344
    User gave us USE_FRM which means that the header in the index file is
 
3345
    trashed.
 
3346
    In this case we will try to fix the table the following way:
 
3347
    - Rename the data file to a temporary name
 
3348
    - Truncate the table
 
3349
    - Replace the new data file with the old one
 
3350
    - Run a normal repair using the new index file and the old data file
 
3351
  */
 
3352
 
 
3353
  /*
 
3354
    Check if this is a table type that stores index and data separately,
 
3355
    like ISAM or MyISAM. We assume fixed order of engine file name
 
3356
    extentions array. First element of engine file name extentions array
 
3357
    is meta/index file extention. Second element - data file extention. 
 
3358
  */
 
3359
  ext= table->file->bas_ext();
 
3360
  if (!ext[0] || !ext[1])
 
3361
    goto end;                                   // No data file
 
3362
 
 
3363
  // Name of data file
 
3364
  strxmov(from, table->s->normalized_path.str, ext[1], NullS);
 
3365
  if (stat(from, &stat_info))
 
3366
    goto end;                           // Can't use USE_FRM flag
 
3367
 
 
3368
  snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
 
3369
           from, current_pid, thd->thread_id);
 
3370
 
 
3371
  /* If we could open the table, close it */
 
3372
  if (table_list->table)
 
3373
  {
 
3374
    pthread_mutex_lock(&LOCK_open);
 
3375
    close_cached_table(thd, table);
 
3376
    pthread_mutex_unlock(&LOCK_open);
 
3377
  }
 
3378
  if (lock_and_wait_for_table_name(thd,table_list))
 
3379
  {
 
3380
    error= -1;
 
3381
    goto end;
 
3382
  }
 
3383
  if (my_rename(from, tmp, MYF(MY_WME)))
 
3384
  {
 
3385
    pthread_mutex_lock(&LOCK_open);
 
3386
    unlock_table_name(thd, table_list);
 
3387
    pthread_mutex_unlock(&LOCK_open);
 
3388
    error= send_check_errmsg(thd, table_list, "repair",
 
3389
                             "Failed renaming data file");
 
3390
    goto end;
 
3391
  }
 
3392
  if (mysql_truncate(thd, table_list, 1))
 
3393
  {
 
3394
    pthread_mutex_lock(&LOCK_open);
 
3395
    unlock_table_name(thd, table_list);
 
3396
    pthread_mutex_unlock(&LOCK_open);
 
3397
    error= send_check_errmsg(thd, table_list, "repair",
 
3398
                             "Failed generating table from .frm file");
 
3399
    goto end;
 
3400
  }
 
3401
  if (my_rename(tmp, from, MYF(MY_WME)))
 
3402
  {
 
3403
    pthread_mutex_lock(&LOCK_open);
 
3404
    unlock_table_name(thd, table_list);
 
3405
    pthread_mutex_unlock(&LOCK_open);
 
3406
    error= send_check_errmsg(thd, table_list, "repair",
 
3407
                             "Failed restoring .MYD file");
 
3408
    goto end;
 
3409
  }
 
3410
 
 
3411
  /*
 
3412
    Now we should be able to open the partially repaired table
 
3413
    to finish the repair in the handler later on.
 
3414
  */
 
3415
  pthread_mutex_lock(&LOCK_open);
 
3416
  if (reopen_name_locked_table(thd, table_list, true))
 
3417
  {
 
3418
    unlock_table_name(thd, table_list);
 
3419
    pthread_mutex_unlock(&LOCK_open);
 
3420
    error= send_check_errmsg(thd, table_list, "repair",
 
3421
                             "Failed to open partially repaired table");
 
3422
    goto end;
 
3423
  }
 
3424
  pthread_mutex_unlock(&LOCK_open);
 
3425
 
 
3426
end:
 
3427
  if (table == &tmp_table)
 
3428
  {
 
3429
    pthread_mutex_lock(&LOCK_open);
 
3430
    closefrm(table, 1);                         // Free allocated memory
 
3431
    pthread_mutex_unlock(&LOCK_open);
 
3432
  }
 
3433
  DBUG_RETURN(error);
 
3434
}
 
3435
 
 
3436
 
1737
3437
 
1738
3438
/*
1739
3439
  RETURN VALUES
1740
3440
    false Message sent to net (admin operation went ok)
1741
 
    true  Message should be sent by caller
 
3441
    true  Message should be sent by caller 
1742
3442
          (admin operation or network communication failed)
1743
3443
*/
1744
 
static bool mysql_admin_table(Session* session, TableList* tables,
 
3444
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
1745
3445
                              HA_CHECK_OPT* check_opt,
1746
3446
                              const char *operator_name,
1747
3447
                              thr_lock_type lock_type,
1748
3448
                              bool open_for_modify,
1749
 
                              int (Cursor::*operator_func)(Session *,
 
3449
                              bool no_warnings_for_error,
 
3450
                              uint extra_open_options,
 
3451
                              int (*prepare_func)(THD *, TABLE_LIST *,
 
3452
                                                  HA_CHECK_OPT *),
 
3453
                              int (handler::*operator_func)(THD *,
1750
3454
                                                            HA_CHECK_OPT *))
1751
3455
{
1752
 
  TableList *table;
1753
 
  Select_Lex *select= &session->lex->select_lex;
 
3456
  TABLE_LIST *table;
 
3457
  SELECT_LEX *select= &thd->lex->select_lex;
1754
3458
  List<Item> field_list;
1755
3459
  Item *item;
1756
 
  LEX *lex= session->lex;
 
3460
  Protocol *protocol= thd->protocol;
 
3461
  LEX *lex= thd->lex;
1757
3462
  int result_code= 0;
1758
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1759
 
  const CHARSET_INFO * const cs= system_charset_info;
 
3463
  CHARSET_INFO *cs= system_charset_info;
 
3464
  DBUG_ENTER("mysql_admin_table");
1760
3465
 
1761
 
  if (! session->endActiveTransaction())
1762
 
    return 1;
 
3466
  if (end_active_trans(thd))
 
3467
    DBUG_RETURN(1);
1763
3468
  field_list.push_back(item = new Item_empty_string("Table",
1764
3469
                                                    NAME_CHAR_LEN * 2,
1765
3470
                                                    cs));
1770
3475
  item->maybe_null = 1;
1771
3476
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1772
3477
  item->maybe_null = 1;
1773
 
  if (session->client->sendFields(&field_list))
1774
 
    return true;
 
3478
  if (protocol->send_fields(&field_list,
 
3479
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
3480
    DBUG_RETURN(true);
 
3481
 
 
3482
  mysql_ha_rm_tables(thd, tables, false);
1775
3483
 
1776
3484
  for (table= tables; table; table= table->next_local)
1777
3485
  {
1779
3487
    char* db = table->db;
1780
3488
    bool fatal_error=0;
1781
3489
 
1782
 
    snprintf(table_name, sizeof(table_name), "%s.%s",db,table->table_name);
 
3490
    DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
 
3491
    DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
 
3492
    strxmov(table_name, db, ".", table->table_name, NullS);
 
3493
    thd->open_options|= extra_open_options;
1783
3494
    table->lock_type= lock_type;
1784
3495
    /* open only one table from local list of command */
1785
3496
    {
1786
 
      TableList *save_next_global, *save_next_local;
 
3497
      TABLE_LIST *save_next_global, *save_next_local;
1787
3498
      save_next_global= table->next_global;
1788
3499
      table->next_global= 0;
1789
3500
      save_next_local= table->next_local;
1790
3501
      table->next_local= 0;
1791
 
      select->table_list.first= (unsigned char*)table;
 
3502
      select->table_list.first= (uchar*)table;
1792
3503
      /*
1793
3504
        Time zone tables and SP tables can be add to lex->query_tables list,
1794
3505
        so it have to be prepared.
1795
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
3506
        TODO: Investigate if we can put extra tables into argument instead of
 
3507
        using lex->query_tables
1796
3508
      */
1797
3509
      lex->query_tables= table;
1798
3510
      lex->query_tables_last= &table->next_global;
1799
3511
      lex->query_tables_own_last= 0;
1800
 
      session->no_warnings_for_error= 0;
 
3512
      thd->no_warnings_for_error= no_warnings_for_error;
 
3513
      table->required_type=FRMTYPE_TABLE;
1801
3514
 
1802
 
      session->openTablesLock(table);
1803
 
      session->no_warnings_for_error= 0;
 
3515
      open_and_lock_tables(thd, table);
 
3516
      thd->no_warnings_for_error= 0;
1804
3517
      table->next_global= save_next_global;
1805
3518
      table->next_local= save_next_local;
 
3519
      thd->open_options&= ~extra_open_options;
 
3520
    }
 
3521
    DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
 
3522
 
 
3523
    if (prepare_func)
 
3524
    {
 
3525
      DBUG_PRINT("admin", ("calling prepare_func"));
 
3526
      switch ((*prepare_func)(thd, table, check_opt)) {
 
3527
      case  1:           // error, message written to net
 
3528
        ha_autocommit_or_rollback(thd, 1);
 
3529
        end_trans(thd, ROLLBACK);
 
3530
        close_thread_tables(thd);
 
3531
        DBUG_PRINT("admin", ("simple error, admin next table"));
 
3532
        continue;
 
3533
      case -1:           // error, message could be written to net
 
3534
        /* purecov: begin inspected */
 
3535
        DBUG_PRINT("admin", ("severe error, stop"));
 
3536
        goto err;
 
3537
        /* purecov: end */
 
3538
      default:           // should be 0 otherwise
 
3539
        DBUG_PRINT("admin", ("prepare_func succeeded"));
 
3540
        ;
 
3541
      }
1806
3542
    }
1807
3543
 
1808
3544
    /*
1809
 
      CHECK Table command is only command where VIEW allowed here and this
 
3545
      CHECK TABLE command is only command where VIEW allowed here and this
1810
3546
      command use only temporary teble method for VIEWs resolving => there
1811
3547
      can't be VIEW tree substitition of join view => if opening table
1812
 
      succeed then table->table will have real Table pointer as value (in
 
3548
      succeed then table->table will have real TABLE pointer as value (in
1813
3549
      case of join view substitution table->table can be 0, but here it is
1814
3550
      impossible)
1815
3551
    */
1816
3552
    if (!table->table)
1817
3553
    {
1818
 
      if (!session->warn_list.elements)
1819
 
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
3554
      DBUG_PRINT("admin", ("open table failed"));
 
3555
      if (!thd->warn_list.elements)
 
3556
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1820
3557
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1821
 
      result_code= HA_ADMIN_CORRUPT;
1822
3558
      goto send_result;
1823
3559
    }
1824
3560
 
1825
3561
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
1826
3562
    {
1827
 
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1828
 
      uint32_t length;
1829
 
      session->client->store(table_name);
1830
 
      session->client->store(operator_name);
1831
 
      session->client->store(STRING_WITH_LEN("error"));
 
3563
      /* purecov: begin inspected */
 
3564
      char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
 
3565
      uint length;
 
3566
      DBUG_PRINT("admin", ("sending error message"));
 
3567
      protocol->prepare_for_resend();
 
3568
      protocol->store(table_name, system_charset_info);
 
3569
      protocol->store(operator_name, system_charset_info);
 
3570
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
1832
3571
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1833
3572
                       table_name);
1834
 
      session->client->store(buff, length);
1835
 
      transaction_services.autocommitOrRollback(session, false);
1836
 
      session->endTransaction(COMMIT);
1837
 
      session->close_thread_tables();
 
3573
      protocol->store(buff, length, system_charset_info);
 
3574
      ha_autocommit_or_rollback(thd, 0);
 
3575
      end_trans(thd, COMMIT);
 
3576
      close_thread_tables(thd);
1838
3577
      lex->reset_query_tables_list(false);
1839
3578
      table->table=0;                           // For query cache
1840
 
      if (session->client->flush())
 
3579
      if (protocol->write())
1841
3580
        goto err;
1842
3581
      continue;
 
3582
      /* purecov: end */
1843
3583
    }
1844
3584
 
1845
3585
    /* Close all instances of the table to allow repair to rename files */
1846
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
3586
    if (lock_type == TL_WRITE && table->table->s->version)
1847
3587
    {
1848
 
      LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1849
 
      const char *old_message=session->enter_cond(COND_refresh, LOCK_open,
1850
 
                                                  "Waiting to get writelock");
1851
 
      mysql_lock_abort(session,table->table);
1852
 
      TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
1853
 
      remove_table_from_cache(session, identifier,
 
3588
      DBUG_PRINT("admin", ("removing table from cache"));
 
3589
      pthread_mutex_lock(&LOCK_open);
 
3590
      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 
3591
                                              "Waiting to get writelock");
 
3592
      mysql_lock_abort(thd,table->table, true);
 
3593
      remove_table_from_cache(thd, table->table->s->db.str,
 
3594
                              table->table->s->table_name.str,
1854
3595
                              RTFC_WAIT_OTHER_THREAD_FLAG |
1855
3596
                              RTFC_CHECK_KILLED_FLAG);
1856
 
      session->exit_cond(old_message);
1857
 
      if (session->killed)
 
3597
      thd->exit_cond(old_message);
 
3598
      DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd););
 
3599
      if (thd->killed)
1858
3600
        goto err;
1859
3601
      open_for_modify= 0;
1860
3602
    }
1861
3603
 
1862
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
3604
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
3605
    {
 
3606
      /* purecov: begin inspected */
 
3607
      DBUG_PRINT("admin", ("sending crashed warning"));
 
3608
      protocol->prepare_for_resend();
 
3609
      protocol->store(table_name, system_charset_info);
 
3610
      protocol->store(operator_name, system_charset_info);
 
3611
      protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
 
3612
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
 
3613
                      system_charset_info);
 
3614
      if (protocol->write())
 
3615
        goto err;
 
3616
      /* purecov: end */
 
3617
    }
 
3618
 
 
3619
    if (operator_func == &handler::ha_repair &&
 
3620
        !(check_opt->sql_flags & TT_USEFRM))
 
3621
    {
 
3622
      if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
 
3623
          (table->table->file->ha_check_for_upgrade(check_opt) ==
 
3624
           HA_ADMIN_NEEDS_ALTER))
 
3625
      {
 
3626
        DBUG_PRINT("admin", ("recreating table"));
 
3627
        ha_autocommit_or_rollback(thd, 1);
 
3628
        close_thread_tables(thd);
 
3629
        tmp_disable_binlog(thd); // binlogging is done by caller if wanted
 
3630
        result_code= mysql_recreate_table(thd, table);
 
3631
        reenable_binlog(thd);
 
3632
        /*
 
3633
          mysql_recreate_table() can push OK or ERROR.
 
3634
          Clear 'OK' status. If there is an error, keep it:
 
3635
          we will store the error message in a result set row 
 
3636
          and then clear.
 
3637
        */
 
3638
        if (thd->main_da.is_ok())
 
3639
          thd->main_da.reset_diagnostics_area();
 
3640
        goto send_result;
 
3641
      }
 
3642
    }
 
3643
 
 
3644
    DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
 
3645
    result_code = (table->table->file->*operator_func)(thd, check_opt);
 
3646
    DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
1863
3647
 
1864
3648
send_result:
1865
3649
 
1866
3650
    lex->cleanup_after_one_table_open();
1867
 
    session->clear_error();  // these errors shouldn't get client
 
3651
    thd->clear_error();  // these errors shouldn't get client
1868
3652
    {
1869
 
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1870
 
      DRIZZLE_ERROR *err;
 
3653
      List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
 
3654
      MYSQL_ERROR *err;
1871
3655
      while ((err= it++))
1872
3656
      {
1873
 
        session->client->store(table_name);
1874
 
        session->client->store(operator_name);
1875
 
        session->client->store(warning_level_names[err->level].str,
1876
 
                               warning_level_names[err->level].length);
1877
 
        session->client->store(err->msg);
1878
 
        if (session->client->flush())
 
3657
        protocol->prepare_for_resend();
 
3658
        protocol->store(table_name, system_charset_info);
 
3659
        protocol->store((char*) operator_name, system_charset_info);
 
3660
        protocol->store(warning_level_names[err->level].str,
 
3661
                        warning_level_names[err->level].length,
 
3662
                        system_charset_info);
 
3663
        protocol->store(err->msg, system_charset_info);
 
3664
        if (protocol->write())
1879
3665
          goto err;
1880
3666
      }
1881
 
      drizzle_reset_errors(session, true);
 
3667
      mysql_reset_errors(thd, true);
1882
3668
    }
1883
 
    session->client->store(table_name);
1884
 
    session->client->store(operator_name);
1885
 
 
 
3669
    protocol->prepare_for_resend();
 
3670
    protocol->store(table_name, system_charset_info);
 
3671
    protocol->store(operator_name, system_charset_info);
 
3672
 
 
3673
send_result_message:
 
3674
 
 
3675
    DBUG_PRINT("info", ("result_code: %d", result_code));
1886
3676
    switch (result_code) {
1887
3677
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
3678
      {
1889
3679
        char buf[ERRMSGSIZE+20];
1890
 
        uint32_t length=snprintf(buf, ERRMSGSIZE,
 
3680
        uint length=snprintf(buf, ERRMSGSIZE,
1891
3681
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1892
 
        session->client->store(STRING_WITH_LEN("note"));
1893
 
        session->client->store(buf, length);
 
3682
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
3683
        protocol->store(buf, length, system_charset_info);
 
3684
      }
 
3685
      break;
 
3686
 
 
3687
    case HA_ADMIN_NOT_BASE_TABLE:
 
3688
      {
 
3689
        char buf[ERRMSGSIZE+20];
 
3690
        uint length= snprintf(buf, ERRMSGSIZE,
 
3691
                              ER(ER_BAD_TABLE_ERROR), table_name);
 
3692
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
3693
        protocol->store(buf, length, system_charset_info);
1894
3694
      }
1895
3695
      break;
1896
3696
 
1897
3697
    case HA_ADMIN_OK:
1898
 
      session->client->store(STRING_WITH_LEN("status"));
1899
 
      session->client->store(STRING_WITH_LEN("OK"));
 
3698
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3699
      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
1900
3700
      break;
1901
3701
 
1902
3702
    case HA_ADMIN_FAILED:
1903
 
      session->client->store(STRING_WITH_LEN("status"));
1904
 
      session->client->store(STRING_WITH_LEN("Operation failed"));
 
3703
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3704
      protocol->store(STRING_WITH_LEN("Operation failed"),
 
3705
                      system_charset_info);
1905
3706
      break;
1906
3707
 
1907
3708
    case HA_ADMIN_REJECT:
1908
 
      session->client->store(STRING_WITH_LEN("status"));
1909
 
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
 
3709
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3710
      protocol->store(STRING_WITH_LEN("Operation need committed state"),
 
3711
                      system_charset_info);
1910
3712
      open_for_modify= false;
1911
3713
      break;
1912
3714
 
1913
3715
    case HA_ADMIN_ALREADY_DONE:
1914
 
      session->client->store(STRING_WITH_LEN("status"));
1915
 
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
 
3716
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3717
      protocol->store(STRING_WITH_LEN("Table is already up to date"),
 
3718
                      system_charset_info);
1916
3719
      break;
1917
3720
 
1918
3721
    case HA_ADMIN_CORRUPT:
1919
 
      session->client->store(STRING_WITH_LEN("error"));
1920
 
      session->client->store(STRING_WITH_LEN("Corrupt"));
 
3722
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3723
      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
1921
3724
      fatal_error=1;
1922
3725
      break;
1923
3726
 
1924
3727
    case HA_ADMIN_INVALID:
1925
 
      session->client->store(STRING_WITH_LEN("error"));
1926
 
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1927
 
      break;
 
3728
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3729
      protocol->store(STRING_WITH_LEN("Invalid argument"),
 
3730
                      system_charset_info);
 
3731
      break;
 
3732
 
 
3733
    case HA_ADMIN_TRY_ALTER:
 
3734
    {
 
3735
      /*
 
3736
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
3737
        "try with alter", so here we close the table, do an ALTER TABLE,
 
3738
        reopen the table and do ha_innobase::analyze() on it.
 
3739
      */
 
3740
      ha_autocommit_or_rollback(thd, 0);
 
3741
      close_thread_tables(thd);
 
3742
      TABLE_LIST *save_next_local= table->next_local,
 
3743
                 *save_next_global= table->next_global;
 
3744
      table->next_local= table->next_global= 0;
 
3745
      tmp_disable_binlog(thd); // binlogging is done by caller if wanted
 
3746
      result_code= mysql_recreate_table(thd, table);
 
3747
      reenable_binlog(thd);
 
3748
      /*
 
3749
        mysql_recreate_table() can push OK or ERROR.
 
3750
        Clear 'OK' status. If there is an error, keep it:
 
3751
        we will store the error message in a result set row 
 
3752
        and then clear.
 
3753
      */
 
3754
      if (thd->main_da.is_ok())
 
3755
        thd->main_da.reset_diagnostics_area();
 
3756
      ha_autocommit_or_rollback(thd, 0);
 
3757
      close_thread_tables(thd);
 
3758
      if (!result_code) // recreation went ok
 
3759
      {
 
3760
        if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
 
3761
            ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
 
3762
          result_code= 0; // analyze went ok
 
3763
      }
 
3764
      if (result_code) // either mysql_recreate_table or analyze failed
 
3765
      {
 
3766
        DBUG_ASSERT(thd->is_error());
 
3767
        if (thd->is_error())
 
3768
        {
 
3769
          const char *err_msg= thd->main_da.message();
 
3770
          if (!thd->vio_ok())
 
3771
          {
 
3772
            sql_print_error(err_msg);
 
3773
          }
 
3774
          else
 
3775
          {
 
3776
            /* Hijack the row already in-progress. */
 
3777
            protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3778
            protocol->store(err_msg, system_charset_info);
 
3779
            (void)protocol->write();
 
3780
            /* Start off another row for HA_ADMIN_FAILED */
 
3781
            protocol->prepare_for_resend();
 
3782
            protocol->store(table_name, system_charset_info);
 
3783
            protocol->store(operator_name, system_charset_info);
 
3784
          }
 
3785
          thd->clear_error();
 
3786
        }
 
3787
      }
 
3788
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
3789
      table->next_local= save_next_local;
 
3790
      table->next_global= save_next_global;
 
3791
      goto send_result_message;
 
3792
    }
 
3793
    case HA_ADMIN_WRONG_CHECKSUM:
 
3794
    {
 
3795
      protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
3796
      protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
 
3797
                      system_charset_info);
 
3798
      break;
 
3799
    }
 
3800
 
 
3801
    case HA_ADMIN_NEEDS_UPGRADE:
 
3802
    case HA_ADMIN_NEEDS_ALTER:
 
3803
    {
 
3804
      char buf[ERRMSGSIZE];
 
3805
      uint length;
 
3806
 
 
3807
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3808
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
3809
      protocol->store(buf, length, system_charset_info);
 
3810
      fatal_error=1;
 
3811
      break;
 
3812
    }
1928
3813
 
1929
3814
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1930
3815
      {
1931
3816
        char buf[ERRMSGSIZE+20];
1932
 
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1933
 
                             _("Unknown - internal error %d during operation"),
 
3817
        uint length=snprintf(buf, ERRMSGSIZE,
 
3818
                             "Unknown - internal error %d during operation",
1934
3819
                             result_code);
1935
 
        session->client->store(STRING_WITH_LEN("error"));
1936
 
        session->client->store(buf, length);
 
3820
        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3821
        protocol->store(buf, length, system_charset_info);
1937
3822
        fatal_error=1;
1938
3823
        break;
1939
3824
      }
1941
3826
    if (table->table)
1942
3827
    {
1943
3828
      if (fatal_error)
1944
 
      {
1945
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1946
 
      }
 
3829
        table->table->s->version=0;               // Force close of table
1947
3830
      else if (open_for_modify)
1948
3831
      {
1949
 
        if (table->table->getShare()->getType())
1950
 
        {
1951
 
          table->table->cursor->info(HA_STATUS_CONST);
1952
 
        }
 
3832
        if (table->table->s->tmp_table)
 
3833
          table->table->file->info(HA_STATUS_CONST);
1953
3834
        else
1954
3835
        {
1955
 
          boost::mutex::scoped_lock lock(LOCK_open);
1956
 
          TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
1957
 
          remove_table_from_cache(session, identifier, RTFC_NO_FLAG);
 
3836
          pthread_mutex_lock(&LOCK_open);
 
3837
          remove_table_from_cache(thd, table->table->s->db.str,
 
3838
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
3839
          pthread_mutex_unlock(&LOCK_open);
1958
3840
        }
1959
3841
      }
1960
3842
    }
1961
 
    transaction_services.autocommitOrRollback(session, false);
1962
 
    session->endTransaction(COMMIT);
1963
 
    session->close_thread_tables();
 
3843
    ha_autocommit_or_rollback(thd, 0);
 
3844
    end_trans(thd, COMMIT);
 
3845
    close_thread_tables(thd);
1964
3846
    table->table=0;                             // For query cache
1965
 
    if (session->client->flush())
 
3847
    if (protocol->write())
1966
3848
      goto err;
1967
3849
  }
1968
3850
 
1969
 
  session->my_eof();
1970
 
  return(false);
 
3851
  my_eof(thd);
 
3852
  DBUG_RETURN(false);
1971
3853
 
1972
3854
err:
1973
 
  transaction_services.autocommitOrRollback(session, true);
1974
 
  session->endTransaction(ROLLBACK);
1975
 
  session->close_thread_tables();                       // Shouldn't be needed
 
3855
  ha_autocommit_or_rollback(thd, 1);
 
3856
  end_trans(thd, ROLLBACK);
 
3857
  close_thread_tables(thd);                     // Shouldn't be needed
1976
3858
  if (table)
1977
3859
    table->table=0;
1978
 
  return(true);
1979
 
}
1980
 
 
1981
 
  /*
1982
 
    Create a new table by copying from source table
1983
 
 
1984
 
    Altough exclusive name-lock on target table protects us from concurrent
1985
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
1986
 
    to plugin::StorageEngine::createTable() in critical section protected by
1987
 
    LOCK_open in order to provide minimal atomicity against operations which
1988
 
    disregard name-locks, like I_S implementation, for example. This is a
1989
 
    temporary and should not be copied. Instead we should fix our code to
1990
 
    always honor name-locks.
1991
 
 
1992
 
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1993
 
    during the call to plugin::StorageEngine::createTable().
1994
 
    See bug #28614 for more info.
1995
 
  */
1996
 
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1997
 
                                 TableIdentifier &destination_identifier,
1998
 
                                 TableIdentifier &src_table,
1999
 
                                 bool is_engine_set)
2000
 
{
2001
 
  int protoerr= EEXIST;
2002
 
  message::Table new_proto;
2003
 
  message::Table src_proto;
2004
 
 
2005
 
  protoerr= plugin::StorageEngine::getTableDefinition(session,
2006
 
                                                      src_table,
2007
 
                                                      src_proto);
2008
 
  new_proto.CopyFrom(src_proto);
2009
 
 
2010
 
  if (destination_identifier.isTmp())
2011
 
  {
2012
 
    new_proto.set_type(message::Table::TEMPORARY);
2013
 
  }
2014
 
  else
2015
 
  {
2016
 
    new_proto.set_type(message::Table::STANDARD);
2017
 
  }
2018
 
 
2019
 
  if (is_engine_set)
2020
 
  {
2021
 
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2022
 
  }
2023
 
 
2024
 
  { // We now do a selective copy of elements on to the new table.
2025
 
    new_proto.set_name(create_table_proto.name());
2026
 
    new_proto.set_schema(create_table_proto.schema());
2027
 
    new_proto.set_catalog(create_table_proto.catalog());
2028
 
  }
2029
 
 
2030
 
  if (protoerr && protoerr != EEXIST)
2031
 
  {
2032
 
    if (errno == ENOENT)
2033
 
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2034
 
    else
2035
 
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2036
 
 
2037
 
    return false;
2038
 
  }
2039
 
 
2040
 
  /*
2041
 
    As mysql_truncate don't work on a new table at this stage of
2042
 
    creation, instead create the table directly (for both normal
2043
 
    and temporary tables).
2044
 
  */
2045
 
  int err= plugin::StorageEngine::createTable(session,
2046
 
                                              destination_identifier,
2047
 
                                              new_proto);
2048
 
 
2049
 
  if (err == false && not destination_identifier.isTmp())
2050
 
  {
2051
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2052
 
    transaction_services.createTable(&session, new_proto);
2053
 
  }
2054
 
 
2055
 
  return err ? false : true;
2056
 
}
 
3860
  DBUG_RETURN(true);
 
3861
}
 
3862
 
 
3863
 
 
3864
bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
3865
{
 
3866
  DBUG_ENTER("mysql_repair_table");
 
3867
  DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 
3868
                                "repair", TL_WRITE, 1,
 
3869
                                test(check_opt->sql_flags & TT_USEFRM),
 
3870
                                HA_OPEN_FOR_REPAIR,
 
3871
                                &prepare_for_repair,
 
3872
                                &handler::ha_repair));
 
3873
}
 
3874
 
 
3875
 
 
3876
bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
3877
{
 
3878
  DBUG_ENTER("mysql_optimize_table");
 
3879
  DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 
3880
                                "optimize", TL_WRITE, 1,0,0,0,
 
3881
                                &handler::ha_optimize));
 
3882
}
 
3883
 
 
3884
 
 
3885
/*
 
3886
  Assigned specified indexes for a table into key cache
 
3887
 
 
3888
  SYNOPSIS
 
3889
    mysql_assign_to_keycache()
 
3890
    thd         Thread object
 
3891
    tables      Table list (one table only)
 
3892
 
 
3893
  RETURN VALUES
 
3894
   false ok
 
3895
   true  error
 
3896
*/
 
3897
 
 
3898
bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
 
3899
                             LEX_STRING *key_cache_name)
 
3900
{
 
3901
  HA_CHECK_OPT check_opt;
 
3902
  KEY_CACHE *key_cache;
 
3903
  DBUG_ENTER("mysql_assign_to_keycache");
 
3904
 
 
3905
  check_opt.init();
 
3906
  pthread_mutex_lock(&LOCK_global_system_variables);
 
3907
  if (!(key_cache= get_key_cache(key_cache_name)))
 
3908
  {
 
3909
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
3910
    my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
 
3911
    DBUG_RETURN(true);
 
3912
  }
 
3913
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
3914
  check_opt.key_cache= key_cache;
 
3915
  DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
 
3916
                                "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
 
3917
                                0, 0, &handler::assign_to_keycache));
 
3918
}
 
3919
 
 
3920
 
 
3921
/*
 
3922
  Reassign all tables assigned to a key cache to another key cache
 
3923
 
 
3924
  SYNOPSIS
 
3925
    reassign_keycache_tables()
 
3926
    thd         Thread object
 
3927
    src_cache   Reference to the key cache to clean up
 
3928
    dest_cache  New key cache
 
3929
 
 
3930
  NOTES
 
3931
    This is called when one sets a key cache size to zero, in which
 
3932
    case we have to move the tables associated to this key cache to
 
3933
    the "default" one.
 
3934
 
 
3935
    One has to ensure that one never calls this function while
 
3936
    some other thread is changing the key cache. This is assured by
 
3937
    the caller setting src_cache->in_init before calling this function.
 
3938
 
 
3939
    We don't delete the old key cache as there may still be pointers pointing
 
3940
    to it for a while after this function returns.
 
3941
 
 
3942
 RETURN VALUES
 
3943
    0     ok
 
3944
*/
 
3945
 
 
3946
int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
 
3947
                             KEY_CACHE *dst_cache)
 
3948
{
 
3949
  DBUG_ENTER("reassign_keycache_tables");
 
3950
 
 
3951
  DBUG_ASSERT(src_cache != dst_cache);
 
3952
  DBUG_ASSERT(src_cache->in_init);
 
3953
  src_cache->param_buff_size= 0;                // Free key cache
 
3954
  ha_resize_key_cache(src_cache);
 
3955
  ha_change_key_cache(src_cache, dst_cache);
 
3956
  DBUG_RETURN(0);
 
3957
}
 
3958
 
 
3959
 
 
3960
 
 
3961
/**
 
3962
  @brief          Create frm file based on I_S table
 
3963
 
 
3964
  @param[in]      thd                      thread handler
 
3965
  @param[in]      schema_table             I_S table           
 
3966
  @param[in]      dst_path                 path where frm should be created
 
3967
  @param[in]      create_info              Create info
 
3968
 
 
3969
  @return         Operation status
 
3970
    @retval       0                        success
 
3971
    @retval       1                        error
 
3972
*/
 
3973
 
 
3974
 
 
3975
bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table,
 
3976
                                  char *dst_path, HA_CREATE_INFO *create_info)
 
3977
{
 
3978
  HA_CREATE_INFO local_create_info;
 
3979
  Alter_info alter_info;
 
3980
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
3981
  uint keys= schema_table->table->s->keys;
 
3982
  uint db_options= 0;
 
3983
  DBUG_ENTER("mysql_create_like_schema_frm");
 
3984
 
 
3985
  bzero((char*) &local_create_info, sizeof(local_create_info));
 
3986
  local_create_info.db_type= schema_table->table->s->db_type();
 
3987
  local_create_info.row_type= schema_table->table->s->row_type;
 
3988
  local_create_info.default_table_charset=default_charset_info;
 
3989
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
3990
  schema_table->table->use_all_columns();
 
3991
  if (mysql_prepare_alter_table(thd, schema_table->table,
 
3992
                                &local_create_info, &alter_info))
 
3993
    DBUG_RETURN(1);
 
3994
  if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
 
3995
                                 tmp_table, &db_options,
 
3996
                                 schema_table->table->file,
 
3997
                                 &schema_table->table->s->key_info, &keys, 0))
 
3998
    DBUG_RETURN(1);
 
3999
  local_create_info.max_rows= 0;
 
4000
  if (mysql_create_frm(thd, dst_path, NullS, NullS,
 
4001
                       &local_create_info, alter_info.create_list,
 
4002
                       keys, schema_table->table->s->key_info,
 
4003
                       schema_table->table->file))
 
4004
    DBUG_RETURN(1);
 
4005
  DBUG_RETURN(0);
 
4006
}
 
4007
 
2057
4008
 
2058
4009
/*
2059
4010
  Create a table identical to the specified table
2060
4011
 
2061
4012
  SYNOPSIS
2062
4013
    mysql_create_like_table()
2063
 
    session             Thread object
 
4014
    thd         Thread object
2064
4015
    table       Table list element for target table
2065
4016
    src_table   Table list element for source table
2066
4017
    create_info Create info
2070
4021
    true  error
2071
4022
*/
2072
4023
 
2073
 
bool mysql_create_like_table(Session* session,
2074
 
                             TableIdentifier &destination_identifier,
2075
 
                             TableList* table, TableList* src_table,
2076
 
                             message::Table &create_table_proto,
2077
 
                             bool is_if_not_exists,
2078
 
                             bool is_engine_set)
 
4024
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
 
4025
                             HA_CREATE_INFO *create_info)
2079
4026
{
 
4027
  TABLE *name_lock= 0;
 
4028
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
4029
  uint dst_path_length;
2080
4030
  char *db= table->db;
2081
4031
  char *table_name= table->table_name;
 
4032
  int  err;
2082
4033
  bool res= true;
2083
 
  uint32_t not_used;
 
4034
  uint not_used;
 
4035
  DBUG_ENTER("mysql_create_like_table");
 
4036
 
 
4037
 
 
4038
  /* CREATE TABLE ... LIKE is not allowed for views. */
 
4039
  src_table->required_type= FRMTYPE_TABLE;
2084
4040
 
2085
4041
  /*
2086
4042
    By opening source table we guarantee that it exists and no concurrent
2087
4043
    DDL operation will mess with it. Later we also take an exclusive
2088
 
    name-lock on target table name, which makes copying of .frm cursor,
2089
 
    call to plugin::StorageEngine::createTable() and binlogging atomic
2090
 
    against concurrent DML and DDL operations on target table.
2091
 
    Thus by holding both these "locks" we ensure that our statement is
2092
 
    properly isolated from all concurrent operations which matter.
 
4044
    name-lock on target table name, which makes copying of .frm file,
 
4045
    call to ha_create_table() and binlogging atomic against concurrent DML
 
4046
    and DDL operations on target table. Thus by holding both these "locks"
 
4047
    we ensure that our statement is properly isolated from all concurrent
 
4048
    operations which matter.
2093
4049
  */
2094
 
  if (session->open_tables_from_list(&src_table, &not_used))
2095
 
    return true;
2096
 
 
2097
 
  TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
2098
 
                                 src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
2099
 
 
2100
 
 
2101
 
 
2102
 
  /*
 
4050
  if (open_tables(thd, &src_table, &not_used, 0))
 
4051
    DBUG_RETURN(true);
 
4052
 
 
4053
  strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
 
4054
 
 
4055
  DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000););
 
4056
 
 
4057
  /* 
2103
4058
    Check that destination tables does not exist. Note that its name
2104
4059
    was already checked when it was added to the table list.
2105
 
 
2106
 
    For temporary tables we don't aim to grab locks.
2107
 
  */
2108
 
  bool table_exists= false;
2109
 
  if (destination_identifier.isTmp())
2110
 
  {
2111
 
    if (session->find_temporary_table(db, table_name))
2112
 
    {
2113
 
      table_exists= true;
2114
 
    }
2115
 
    else
2116
 
    {
2117
 
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2118
 
                                             src_identifier, is_engine_set);
2119
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2120
 
      {
2121
 
        (void) session->rm_temporary_table(destination_identifier, true);
2122
 
      }
2123
 
      else if (not session->open_temporary_table(destination_identifier))
2124
 
      {
2125
 
        // We created, but we can't open... also, a hack.
2126
 
        (void) session->rm_temporary_table(destination_identifier, true);
2127
 
      }
2128
 
      else
2129
 
      {
2130
 
        res= false;
2131
 
      }
2132
 
    }
2133
 
  }
2134
 
  else // Standard table which will require locks.
2135
 
  {
2136
 
    Table *name_lock= 0;
2137
 
 
2138
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2139
 
    {
2140
 
      if (name_lock)
2141
 
      {
2142
 
        boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2143
 
        session->unlink_open_table(name_lock);
2144
 
      }
2145
 
 
2146
 
      return res;
2147
 
    }
2148
 
 
2149
 
    if (not name_lock)
2150
 
    {
2151
 
      table_exists= true;
2152
 
    }
2153
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2154
 
    {
2155
 
      table_exists= true;
2156
 
    }
2157
 
    else // Otherwise we create the table
2158
 
    {
2159
 
      bool was_created;
2160
 
      {
2161
 
        boost::mutex::scoped_lock lock(LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2162
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2163
 
                                               src_identifier, is_engine_set);
2164
 
      }
2165
 
 
2166
 
      // So we blew the creation of the table, and we scramble to clean up
2167
 
      // anything that might have been created (read... it is a hack)
2168
 
      if (not was_created)
2169
 
      {
2170
 
        quick_rm_table(*session, destination_identifier);
2171
 
      } 
2172
 
      else
2173
 
      {
2174
 
        res= false;
2175
 
      }
2176
 
    }
2177
 
 
 
4060
  */
 
4061
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
4062
  {
 
4063
    if (find_temporary_table(thd, db, table_name))
 
4064
      goto table_exists;
 
4065
    dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
 
4066
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
 
4067
  }
 
4068
  else
 
4069
  {
 
4070
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
4071
      goto err;
 
4072
    if (!name_lock)
 
4073
      goto table_exists;
 
4074
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
4075
                                          db, table_name, reg_ext, 0);
 
4076
    if (!access(dst_path, F_OK))
 
4077
      goto table_exists;
 
4078
  }
 
4079
 
 
4080
  DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
 
4081
 
 
4082
  /*
 
4083
    Create a new table by copying from source table
 
4084
 
 
4085
    Altough exclusive name-lock on target table protects us from concurrent
 
4086
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
4087
    to ha_create_table() in critical section protected by LOCK_open in order
 
4088
    to provide minimal atomicity against operations which disregard name-locks,
 
4089
    like I_S implementation, for example. This is a temporary and should not
 
4090
    be copied. Instead we should fix our code to always honor name-locks.
 
4091
 
 
4092
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
4093
    during the call to ha_create_table(). See bug #28614 for more info.
 
4094
  */
 
4095
  VOID(pthread_mutex_lock(&LOCK_open));
 
4096
  if (src_table->schema_table)
 
4097
  {
 
4098
    if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
 
4099
    {
 
4100
      VOID(pthread_mutex_unlock(&LOCK_open));
 
4101
      goto err;
 
4102
    }
 
4103
  }
 
4104
  else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
 
4105
  {
 
4106
    if (my_errno == ENOENT)
 
4107
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
4108
    else
 
4109
      my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
4110
    VOID(pthread_mutex_unlock(&LOCK_open));
 
4111
    goto err;
 
4112
  }
 
4113
 
 
4114
  /*
 
4115
    As mysql_truncate don't work on a new table at this stage of
 
4116
    creation, instead create the table directly (for both normal
 
4117
    and temporary tables).
 
4118
  */
 
4119
  DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000););
 
4120
 
 
4121
  dst_path[dst_path_length - reg_ext_length]= '\0';  // Remove .frm
 
4122
  if (thd->variables.keep_files_on_create)
 
4123
    create_info->options|= HA_CREATE_KEEP_FILES;
 
4124
  err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
 
4125
  VOID(pthread_mutex_unlock(&LOCK_open));
 
4126
 
 
4127
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
4128
  {
 
4129
    if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
 
4130
                                     OTM_OPEN))
 
4131
    {
 
4132
      (void) rm_temporary_table(create_info->db_type,
 
4133
                                dst_path, false); /* purecov: inspected */
 
4134
      goto err;     /* purecov: inspected */
 
4135
    }
 
4136
  }
 
4137
  else if (err)
 
4138
  {
 
4139
    (void) quick_rm_table(create_info->db_type, db,
 
4140
                          table_name, 0); /* purecov: inspected */
 
4141
    goto err;       /* purecov: inspected */
 
4142
  }
 
4143
 
 
4144
  DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
 
4145
 
 
4146
  /*
 
4147
    We have to write the query before we unlock the tables.
 
4148
  */
 
4149
  if (thd->current_stmt_binlog_row_based)
 
4150
  {
 
4151
    /*
 
4152
       Since temporary tables are not replicated under row-based
 
4153
       replication, CREATE TABLE ... LIKE ... needs special
 
4154
       treatement.  We have four cases to consider, according to the
 
4155
       following decision table:
 
4156
 
 
4157
           ==== ========= ========= ==============================
 
4158
           Case    Target    Source Write to binary log
 
4159
           ==== ========= ========= ==============================
 
4160
           1       normal    normal Original statement
 
4161
           2       normal temporary Generated statement
 
4162
           3    temporary    normal Nothing
 
4163
           4    temporary temporary Nothing
 
4164
           ==== ========= ========= ==============================
 
4165
    */
 
4166
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
4167
    {
 
4168
      if (src_table->table->s->tmp_table)               // Case 2
 
4169
      {
 
4170
        char buf[2048];
 
4171
        String query(buf, sizeof(buf), system_charset_info);
 
4172
        query.length(0);  // Have to zero it since constructor doesn't
 
4173
 
 
4174
 
 
4175
        /*
 
4176
          Here we open the destination table, on which we already have
 
4177
          name-lock. This is needed for store_create_info() to work.
 
4178
          The table will be closed by unlink_open_table() at the end
 
4179
          of this function.
 
4180
        */
 
4181
        table->table= name_lock;
 
4182
        VOID(pthread_mutex_lock(&LOCK_open));
 
4183
        if (reopen_name_locked_table(thd, table, false))
 
4184
        {
 
4185
          VOID(pthread_mutex_unlock(&LOCK_open));
 
4186
          goto err;
 
4187
        }
 
4188
        VOID(pthread_mutex_unlock(&LOCK_open));
 
4189
 
 
4190
        IF_DBUG(int result=) store_create_info(thd, table, &query,
 
4191
                                               create_info);
 
4192
 
 
4193
        DBUG_ASSERT(result == 0); // store_create_info() always return 0
 
4194
        write_bin_log(thd, true, query.ptr(), query.length());
 
4195
      }
 
4196
      else                                      // Case 1
 
4197
        write_bin_log(thd, true, thd->query, thd->query_length);
 
4198
    }
 
4199
    /*
 
4200
      Case 3 and 4 does nothing under RBR
 
4201
    */
 
4202
  }
 
4203
  else
 
4204
    write_bin_log(thd, true, thd->query, thd->query_length);
 
4205
 
 
4206
  res= false;
 
4207
  goto err;
 
4208
 
 
4209
table_exists:
 
4210
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
4211
  {
 
4212
    char warn_buff[MYSQL_ERRMSG_SIZE];
 
4213
    snprintf(warn_buff, sizeof(warn_buff),
 
4214
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
4215
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
4216
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
4217
    res= false;
 
4218
  }
 
4219
  else
 
4220
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
4221
 
 
4222
err:
 
4223
  if (name_lock)
 
4224
  {
 
4225
    pthread_mutex_lock(&LOCK_open);
 
4226
    unlink_open_table(thd, name_lock, false);
 
4227
    pthread_mutex_unlock(&LOCK_open);
 
4228
  }
 
4229
  DBUG_RETURN(res);
 
4230
}
 
4231
 
 
4232
 
 
4233
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
4234
{
 
4235
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
4236
 
 
4237
  DBUG_ENTER("mysql_analyze_table");
 
4238
  DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 
4239
                                "analyze", lock_type, 1, 0, 0, 0,
 
4240
                                &handler::ha_analyze));
 
4241
}
 
4242
 
 
4243
 
 
4244
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
 
4245
{
 
4246
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
4247
 
 
4248
  DBUG_ENTER("mysql_check_table");
 
4249
  DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 
4250
                                "check", lock_type,
 
4251
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
4252
                                &handler::ha_check));
 
4253
}
 
4254
 
 
4255
 
 
4256
/* table_list should contain just one table */
 
4257
static int
 
4258
mysql_discard_or_import_tablespace(THD *thd,
 
4259
                                   TABLE_LIST *table_list,
 
4260
                                   enum tablespace_op_type tablespace_op)
 
4261
{
 
4262
  TABLE *table;
 
4263
  my_bool discard;
 
4264
  int error;
 
4265
  DBUG_ENTER("mysql_discard_or_import_tablespace");
 
4266
 
 
4267
  /*
 
4268
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
 
4269
    ALTER TABLE
 
4270
  */
 
4271
 
 
4272
  thd_proc_info(thd, "discard_or_import_tablespace");
 
4273
 
 
4274
  discard= test(tablespace_op == DISCARD_TABLESPACE);
 
4275
 
 
4276
 /*
 
4277
   We set this flag so that ha_innobase::open and ::external_lock() do
 
4278
   not complain when we lock the table
 
4279
 */
 
4280
  thd->tablespace_op= true;
 
4281
  if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
 
4282
  {
 
4283
    thd->tablespace_op=false;
 
4284
    DBUG_RETURN(-1);
 
4285
  }
 
4286
 
 
4287
  error= table->file->ha_discard_or_import_tablespace(discard);
 
4288
 
 
4289
  thd_proc_info(thd, "end");
 
4290
 
 
4291
  if (error)
 
4292
    goto err;
 
4293
 
 
4294
  /* The ALTER TABLE is always in its own transaction */
 
4295
  error = ha_autocommit_or_rollback(thd, 0);
 
4296
  if (end_active_trans(thd))
 
4297
    error=1;
 
4298
  if (error)
 
4299
    goto err;
 
4300
  write_bin_log(thd, false, thd->query, thd->query_length);
 
4301
 
 
4302
err:
 
4303
  ha_autocommit_or_rollback(thd, error);
 
4304
  thd->tablespace_op=false;
 
4305
  
 
4306
  if (error == 0)
 
4307
  {
 
4308
    my_ok(thd);
 
4309
    DBUG_RETURN(0);
 
4310
  }
 
4311
 
 
4312
  table->file->print_error(error, MYF(0));
 
4313
    
 
4314
  DBUG_RETURN(-1);
 
4315
}
 
4316
 
 
4317
/**
 
4318
  Copy all changes detected by parser to the HA_ALTER_FLAGS
 
4319
*/
 
4320
 
 
4321
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
 
4322
{
 
4323
  uint flags= alter_info->flags;
 
4324
 
 
4325
  if (ALTER_ADD_COLUMN & flags)
 
4326
    *alter_flags|= HA_ADD_COLUMN;
 
4327
  if (ALTER_DROP_COLUMN & flags)
 
4328
    *alter_flags|= HA_DROP_COLUMN;
 
4329
  if (ALTER_RENAME & flags)
 
4330
    *alter_flags|= HA_RENAME_TABLE;
 
4331
  if (ALTER_CHANGE_COLUMN & flags)
 
4332
    *alter_flags|= HA_CHANGE_COLUMN;
 
4333
  if (ALTER_COLUMN_DEFAULT & flags)
 
4334
    *alter_flags|= HA_COLUMN_DEFAULT_VALUE;
 
4335
  if (ALTER_COLUMN_STORAGE & flags)
 
4336
    *alter_flags|= HA_COLUMN_STORAGE;
 
4337
  if (ALTER_COLUMN_FORMAT & flags)
 
4338
    *alter_flags|= HA_COLUMN_FORMAT;
 
4339
  if (ALTER_COLUMN_ORDER & flags)
 
4340
    *alter_flags|= HA_ALTER_COLUMN_ORDER;
 
4341
  if (ALTER_STORAGE & flags)
 
4342
    *alter_flags|= HA_ALTER_STORAGE;
 
4343
  if (ALTER_ROW_FORMAT & flags)
 
4344
    *alter_flags|= HA_ALTER_ROW_FORMAT;
 
4345
  if (ALTER_RECREATE & flags)
 
4346
    *alter_flags|= HA_RECREATE;
 
4347
  if (ALTER_FOREIGN_KEY & flags)
 
4348
    *alter_flags|= HA_ALTER_FOREIGN_KEY;
 
4349
}
 
4350
 
 
4351
 
 
4352
/**
 
4353
   @param       thd                Thread
 
4354
   @param       table              The original table.
 
4355
   @param       alter_info         Alter options, fields and keys for the new
 
4356
                                   table.
 
4357
   @param       create_info        Create options for the new table.
 
4358
   @param       order_num          Number of order list elements.
 
4359
   @param[out]  ha_alter_flags  Flags that indicate what will be changed
 
4360
   @param[out]  ha_alter_info      Data structures needed for on-line alter
 
4361
   @param[out]  table_changes      Information about particular change
 
4362
 
 
4363
   First argument 'table' contains information of the original
 
4364
   table, which includes all corresponding parts that the new
 
4365
   table has in arguments create_list, key_list and create_info.
 
4366
 
 
4367
   By comparing the changes between the original and new table
 
4368
   we can determine how much it has changed after ALTER TABLE
 
4369
   and whether we need to make a copy of the table, or just change
 
4370
   the .frm file.
 
4371
 
 
4372
   Mark any changes detected in the ha_alter_flags.
 
4373
 
 
4374
   If there are no data changes, but index changes, 'index_drop_buffer'
 
4375
   and/or 'index_add_buffer' are populated with offsets into
 
4376
   table->key_info or key_info_buffer respectively for the indexes
 
4377
   that need to be dropped and/or (re-)created.
 
4378
 
 
4379
   @retval true  error
 
4380
   @retval false success
 
4381
*/
 
4382
 
 
4383
static
 
4384
bool
 
4385
compare_tables(THD *thd,
 
4386
               TABLE *table,
 
4387
               Alter_info *alter_info,
 
4388
                           HA_CREATE_INFO *create_info,
 
4389
               uint order_num,
 
4390
               HA_ALTER_FLAGS *alter_flags,
 
4391
               HA_ALTER_INFO *ha_alter_info,
 
4392
               uint *table_changes)
 
4393
{
 
4394
  Field **f_ptr, *field;
 
4395
  uint table_changes_local= 0;
 
4396
  List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
 
4397
  Create_field *new_field;
 
4398
  KEY_PART_INFO *key_part;
 
4399
  KEY_PART_INFO *end;
 
4400
  /*
 
4401
    Remember if the new definition has new VARCHAR column;
 
4402
    create_info->varchar will be reset in mysql_prepare_create_table.
 
4403
  */
 
4404
  bool varchar= create_info->varchar;
 
4405
  DBUG_ENTER("compare_tables");
 
4406
 
 
4407
  {
 
4408
    /*
 
4409
      Create a copy of alter_info.
 
4410
      To compare the new and old table definitions, we need to "prepare"
 
4411
      the new definition - transform it from parser output to a format
 
4412
      that describes the final table layout (all column defaults are
 
4413
      initialized, duplicate columns are removed). This is done by
 
4414
      mysql_prepare_create_table.  Unfortunately,
 
4415
      mysql_prepare_create_table performs its transformations
 
4416
      "in-place", that is, modifies the argument.  Since we would
 
4417
      like to keep compare_tables() idempotent (not altering any
 
4418
      of the arguments) we create a copy of alter_info here and
 
4419
      pass it to mysql_prepare_create_table, then use the result
 
4420
      to evaluate possibility of fast ALTER TABLE, and then
 
4421
      destroy the copy.
 
4422
    */
 
4423
    Alter_info tmp_alter_info(*alter_info, thd->mem_root);
 
4424
    THD *thd= table->in_use;
 
4425
    uint db_options= 0; /* not used */
 
4426
    /* Create the prepared information. */
 
4427
    if (mysql_prepare_create_table(thd, create_info,
 
4428
                                   &tmp_alter_info,
 
4429
                                   (table->s->tmp_table != NO_TMP_TABLE),
 
4430
                                   &db_options,
 
4431
                                   table->file,
 
4432
                                   &ha_alter_info->key_info_buffer,
 
4433
                                   &ha_alter_info->key_count,
 
4434
                                   /* select_field_count */ 0))
 
4435
      DBUG_RETURN(true);
 
4436
    /* Allocate result buffers. */
 
4437
    if (! (ha_alter_info->index_drop_buffer=
 
4438
           (uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
 
4439
        ! (ha_alter_info->index_add_buffer=
 
4440
           (uint*) thd->alloc(sizeof(uint) *
 
4441
                              tmp_alter_info.key_list.elements)))
 
4442
      DBUG_RETURN(true);
 
4443
  }
 
4444
  /*
 
4445
    First we setup ha_alter_flags based on what was detected
 
4446
    by parser
 
4447
  */
 
4448
  setup_ha_alter_flags(alter_info, alter_flags);
 
4449
 
 
4450
#ifndef DBUG_OFF
 
4451
  {
 
4452
    char dbug_string[HA_MAX_ALTER_FLAGS+1];
 
4453
    alter_flags->print(dbug_string);
 
4454
    DBUG_PRINT("info", ("alter_flags:  %s", (char *) dbug_string));
 
4455
  }
 
4456
#endif
 
4457
 
 
4458
  /*
 
4459
    Some very basic checks. If number of fields changes, or the
 
4460
    handler, we need to run full ALTER TABLE. In the future
 
4461
    new fields can be added and old dropped without copy, but
 
4462
    not yet.
 
4463
 
 
4464
    Test also that engine was not given during ALTER TABLE, or
 
4465
    we are force to run regular alter table (copy).
 
4466
    E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
 
4467
 
 
4468
    For the following ones we also want to run regular alter table:
 
4469
    ALTER TABLE tbl_name ORDER BY ..
 
4470
    ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
 
4471
 
 
4472
    At the moment we can't handle altering temporary tables without a copy.
 
4473
    We also test if OPTIMIZE TABLE was given and was mapped to alter table.
 
4474
    In that case we always do full copy.
 
4475
 
 
4476
    There was a bug prior to mysql-4.0.25. Number of null fields was
 
4477
    calculated incorrectly. As a result frm and data files gets out of
 
4478
    sync after fast alter table. There is no way to determine by which
 
4479
    mysql version (in 4.0 and 4.1 branches) table was created, thus we
 
4480
    disable fast alter table for all tables created by mysql versions
 
4481
    prior to 5.0 branch.
 
4482
    See BUG#6236.
 
4483
  */
 
4484
  if (table->s->fields != alter_info->create_list.elements ||
 
4485
      table->s->db_type() != create_info->db_type ||
 
4486
      table->s->tmp_table ||
 
4487
      create_info->used_fields & HA_CREATE_USED_ENGINE ||
 
4488
      create_info->used_fields & HA_CREATE_USED_CHARSET ||
 
4489
      create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
 
4490
      create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
 
4491
      (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
 
4492
      order_num ||
 
4493
      !table->s->mysql_version ||
 
4494
      (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
 
4495
  {
 
4496
    *table_changes= IS_EQUAL_NO;
 
4497
    /*
 
4498
      Check what has changed and set alter_flags
 
4499
    */
 
4500
    if (table->s->fields < alter_info->create_list.elements)
 
4501
      *alter_flags|= HA_ADD_COLUMN;
 
4502
    else if (table->s->fields > alter_info->create_list.elements)
 
4503
      *alter_flags|= HA_DROP_COLUMN;
 
4504
    if (create_info->db_type != table->s->db_type() ||
 
4505
        create_info->used_fields & HA_CREATE_USED_ENGINE)
 
4506
      *alter_flags|= HA_ALTER_STORAGE_ENGINE;
 
4507
    if (create_info->used_fields & HA_CREATE_USED_CHARSET)
 
4508
      *alter_flags|= HA_CHANGE_CHARACTER_SET;
 
4509
    if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
 
4510
      *alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
 
4511
    if (alter_info->flags & ALTER_RECREATE)
 
4512
      *alter_flags|= HA_RECREATE;
 
4513
    /* TODO check for ADD/DROP FOREIGN KEY */
 
4514
    if (alter_info->flags & ALTER_FOREIGN_KEY)
 
4515
      *alter_flags|=  HA_ALTER_FOREIGN_KEY;
 
4516
    if (!table->s->mysql_version ||
 
4517
        (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
 
4518
      *alter_flags|=  HA_ALTER_COLUMN_TYPE;
 
4519
  }
 
4520
  /*
 
4521
    Go through fields and check if the original ones are compatible
 
4522
    with new table.
 
4523
  */
 
4524
  for (f_ptr= table->field, new_field= new_field_it++;
 
4525
       (new_field && (field= *f_ptr));
 
4526
       f_ptr++, new_field= new_field_it++)
 
4527
  {
 
4528
    /* Make sure we have at least the default charset in use. */
 
4529
    if (!new_field->charset)
 
4530
      new_field->charset= create_info->default_table_charset;
 
4531
 
 
4532
    /* Don't pack rows in old tables if the user has requested this. */
 
4533
    if (create_info->row_type == ROW_TYPE_DYNAMIC ||
 
4534
        (new_field->flags & BLOB_FLAG) ||
 
4535
        (new_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
 
4536
      create_info->table_options|= HA_OPTION_PACK_RECORD;
 
4537
 
 
4538
    /* Check how fields have been modified */
 
4539
    if (alter_info->flags & ALTER_CHANGE_COLUMN)
 
4540
    {
 
4541
      /* Evaluate changes bitmap and send to check_if_incompatible_data() */
 
4542
      if (!(table_changes_local= field->is_equal(new_field)))
 
4543
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
4544
 
 
4545
      /* Check if field was renamed */
 
4546
      field->flags&= ~FIELD_IS_RENAMED;
 
4547
      if (my_strcasecmp(system_charset_info,
 
4548
                        field->field_name,
 
4549
                        new_field->field_name))
 
4550
      {
 
4551
        field->flags|= FIELD_IS_RENAMED;
 
4552
        *alter_flags|= HA_ALTER_COLUMN_NAME;
 
4553
      }
 
4554
 
 
4555
      *table_changes&= table_changes_local;
 
4556
      if (table_changes_local == IS_EQUAL_PACK_LENGTH)
 
4557
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
4558
 
 
4559
      /* Check that NULL behavior is same for old and new fields */
 
4560
      if ((new_field->flags & NOT_NULL_FLAG) !=
 
4561
          (uint) (field->flags & NOT_NULL_FLAG))
 
4562
      {
 
4563
        *table_changes= IS_EQUAL_NO;
 
4564
        *alter_flags|= HA_ALTER_COLUMN_NULLABLE;
 
4565
      }
 
4566
    }
 
4567
 
 
4568
    /* Clear indexed marker */
 
4569
    field->flags&= ~FIELD_IN_ADD_INDEX;
 
4570
  }
 
4571
 
 
4572
  /*
 
4573
    Go through keys and check if the original ones are compatible
 
4574
    with new table.
 
4575
  */
 
4576
  KEY *table_key;
 
4577
  KEY *table_key_end= table->key_info + table->s->keys;
 
4578
  KEY *new_key;
 
4579
  KEY *new_key_end=
 
4580
       ha_alter_info->key_info_buffer + ha_alter_info->key_count;
 
4581
 
 
4582
  DBUG_PRINT("info", ("index count old: %d  new: %d",
 
4583
                      table->s->keys, ha_alter_info->key_count));
 
4584
  /*
 
4585
    Step through all keys of the old table and search matching new keys.
 
4586
  */
 
4587
  ha_alter_info->index_drop_count= 0;
 
4588
  ha_alter_info->index_add_count= 0;
 
4589
  for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
4590
  {
 
4591
    KEY_PART_INFO *table_part;
 
4592
    KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
 
4593
    KEY_PART_INFO *new_part;
 
4594
 
 
4595
    /* Search a new key with the same name. */
 
4596
    for (new_key= ha_alter_info->key_info_buffer;
 
4597
         new_key < new_key_end;
 
4598
         new_key++)
 
4599
    {
 
4600
      if (! strcmp(table_key->name, new_key->name))
 
4601
        break;
 
4602
    }
 
4603
    if (new_key >= new_key_end)
 
4604
    {
 
4605
      /* Key not found. Add the offset of the key to the drop buffer. */
 
4606
      ha_alter_info->index_drop_buffer
 
4607
           [ha_alter_info->index_drop_count++]=
 
4608
           table_key - table->key_info;
 
4609
      if (table_key->flags & HA_NOSAME)
 
4610
      {
 
4611
        /* Unique key. Check for "PRIMARY". */
 
4612
        if (! my_strcasecmp(system_charset_info,
 
4613
                            table_key->name, primary_key_name))
 
4614
          *alter_flags|= HA_DROP_PK_INDEX;
 
4615
        else
 
4616
          *alter_flags|= HA_DROP_UNIQUE_INDEX;
 
4617
      }
 
4618
      else
 
4619
        *alter_flags|= HA_DROP_INDEX;
 
4620
      *table_changes= IS_EQUAL_NO;
 
4621
      DBUG_PRINT("info", ("index dropped: '%s'", table_key->name));
 
4622
      continue;
 
4623
    }
 
4624
 
 
4625
    /* Check that the key types are compatible between old and new tables. */
 
4626
    if ((table_key->algorithm != new_key->algorithm) ||
 
4627
        ((table_key->flags & HA_KEYFLAG_MASK) !=
 
4628
         (new_key->flags & HA_KEYFLAG_MASK)) ||
 
4629
        (table_key->key_parts != new_key->key_parts))
 
4630
    {
 
4631
      if (table_key->flags & HA_NOSAME)
 
4632
      {
 
4633
        // Unique key. Check for "PRIMARY".
 
4634
        if (! my_strcasecmp(system_charset_info,
 
4635
                            table_key->name, primary_key_name))
 
4636
          *alter_flags|= HA_ALTER_PK_INDEX;
 
4637
        else
 
4638
          *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
4639
      }
 
4640
      else
 
4641
        *alter_flags|= HA_ALTER_INDEX;
 
4642
      goto index_changed;
 
4643
    }
 
4644
 
 
4645
    /*
 
4646
      Check that the key parts remain compatible between the old and
 
4647
      new tables.
 
4648
    */
 
4649
    for (table_part= table_key->key_part, new_part= new_key->key_part;
 
4650
         table_part < table_part_end;
 
4651
         table_part++, new_part++)
 
4652
    {
 
4653
      /*
 
4654
        Key definition has changed if we are using a different field or
 
4655
        if the used key part length is different. We know that the fields
 
4656
        did not change. Comparing field numbers is sufficient.
 
4657
      */
 
4658
      if ((table_part->length != new_part->length) ||
 
4659
          (table_part->fieldnr - 1 != new_part->fieldnr))
 
4660
      {
 
4661
        if (table_key->flags & HA_NOSAME)
 
4662
        {
 
4663
          /* Unique key. Check for "PRIMARY" */
 
4664
          if (! my_strcasecmp(system_charset_info,
 
4665
                              table_key->name, primary_key_name))
 
4666
            *alter_flags|= HA_ALTER_PK_INDEX;
 
4667
          else
 
4668
            *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
4669
        }
 
4670
        else
 
4671
          *alter_flags|= HA_ALTER_INDEX;
 
4672
        goto index_changed;
 
4673
      }
 
4674
    }
 
4675
    continue;
 
4676
 
 
4677
  index_changed:
 
4678
    /* Key modified. Add the offset of the key to both buffers. */
 
4679
    ha_alter_info->index_drop_buffer
 
4680
         [ha_alter_info->index_drop_count++]=
 
4681
         table_key - table->key_info;
 
4682
    ha_alter_info->index_add_buffer
 
4683
         [ha_alter_info->index_add_count++]=
 
4684
         new_key - ha_alter_info->key_info_buffer;
 
4685
    key_part= new_key->key_part;
 
4686
    end= key_part + new_key->key_parts;
 
4687
    for(; key_part != end; key_part++)
 
4688
    {
 
4689
      /* Mark field to be part of new key */
 
4690
      if ((field= table->field[key_part->fieldnr]))
 
4691
        field->flags|= FIELD_IN_ADD_INDEX;
 
4692
    }
 
4693
    *table_changes= IS_EQUAL_NO;
 
4694
    DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
 
4695
  }
 
4696
  /*end of for (; table_key < table_key_end;) */
 
4697
 
 
4698
  /*
 
4699
    Step through all keys of the new table and find matching old keys.
 
4700
  */
 
4701
  for (new_key= ha_alter_info->key_info_buffer;
 
4702
       new_key < new_key_end;
 
4703
       new_key++)
 
4704
  {
 
4705
    /* Search an old key with the same name. */
 
4706
    for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
4707
    {
 
4708
      if (! strcmp(table_key->name, new_key->name))
 
4709
        break;
 
4710
    }
 
4711
    if (table_key >= table_key_end)
 
4712
    {
 
4713
      /* Key not found. Add the offset of the key to the add buffer. */
 
4714
      ha_alter_info->index_add_buffer
 
4715
           [ha_alter_info->index_add_count++]=
 
4716
           new_key - ha_alter_info->key_info_buffer;
 
4717
      key_part= new_key->key_part;
 
4718
      end= key_part + new_key->key_parts;
 
4719
      for(; key_part != end; key_part++)
 
4720
      {
 
4721
        /* Mark field to be part of new key */
 
4722
        if ((field= table->field[key_part->fieldnr]))
 
4723
          field->flags|= FIELD_IN_ADD_INDEX;
 
4724
      }
 
4725
      if (new_key->flags & HA_NOSAME)
 
4726
      {
 
4727
        /* Unique key. Check for "PRIMARY" */
 
4728
        if (! my_strcasecmp(system_charset_info,
 
4729
                            new_key->name, primary_key_name))
 
4730
          *alter_flags|= HA_ADD_PK_INDEX;
 
4731
        else
 
4732
        *alter_flags|= HA_ADD_UNIQUE_INDEX;
 
4733
      }
 
4734
      else
 
4735
        *alter_flags|= HA_ADD_INDEX;
 
4736
      *table_changes= IS_EQUAL_NO;
 
4737
      DBUG_PRINT("info", ("index added: '%s'", new_key->name));
 
4738
    }
 
4739
  }
 
4740
#ifndef DBUG_OFF
 
4741
  {
 
4742
    char dbug_string[HA_MAX_ALTER_FLAGS+1];
 
4743
    alter_flags->print(dbug_string);
 
4744
    DBUG_PRINT("info", ("alter_flags:  %s", (char *) dbug_string));
 
4745
  }
 
4746
#endif
 
4747
 
 
4748
  DBUG_RETURN(false);
 
4749
}
 
4750
 
 
4751
 
 
4752
/*
 
4753
  Manages enabling/disabling of indexes for ALTER TABLE
 
4754
 
 
4755
  SYNOPSIS
 
4756
    alter_table_manage_keys()
 
4757
      table                  Target table
 
4758
      indexes_were_disabled  Whether the indexes of the from table
 
4759
                             were disabled
 
4760
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
 
4761
 
 
4762
  RETURN VALUES
 
4763
    false  OK
 
4764
    true   Error
 
4765
*/
 
4766
 
 
4767
static
 
4768
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
 
4769
                             enum enum_enable_or_disable keys_onoff)
 
4770
{
 
4771
  int error= 0;
 
4772
  DBUG_ENTER("alter_table_manage_keys");
 
4773
  DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
 
4774
             table, indexes_were_disabled, keys_onoff));
 
4775
 
 
4776
  switch (keys_onoff) {
 
4777
  case ENABLE:
 
4778
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4779
    break;
 
4780
  case LEAVE_AS_IS:
 
4781
    if (!indexes_were_disabled)
 
4782
      break;
 
4783
    /* fall-through: disabled indexes */
 
4784
  case DISABLE:
 
4785
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4786
  }
 
4787
 
 
4788
  if (error == HA_ERR_WRONG_COMMAND)
 
4789
  {
 
4790
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
4791
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
4792
                        table->s->table_name.str);
 
4793
    error= 0;
 
4794
  } else if (error)
 
4795
    table->file->print_error(error, MYF(0));
 
4796
 
 
4797
  DBUG_RETURN(error);
 
4798
}
 
4799
 
 
4800
int create_temporary_table(THD *thd,
 
4801
                           TABLE *table,
 
4802
                           char *new_db,
 
4803
                           char *tmp_name,
 
4804
                           HA_CREATE_INFO *create_info,
 
4805
                           Alter_info *alter_info,
 
4806
                           bool db_changed)
 
4807
{
 
4808
  int error;
 
4809
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
 
4810
  handlerton *old_db_type, *new_db_type;
 
4811
  DBUG_ENTER("create_temporary_table");
 
4812
  old_db_type= table->s->db_type();
 
4813
  new_db_type= create_info->db_type;
 
4814
  /*
 
4815
    Handling of symlinked tables:
 
4816
    If no rename:
 
4817
      Create new data file and index file on the same disk as the
 
4818
      old data and index files.
 
4819
      Copy data.
 
4820
      Rename new data file over old data file and new index file over
 
4821
      old index file.
 
4822
      Symlinks are not changed.
 
4823
 
 
4824
   If rename:
 
4825
      Create new data file and index file on the same disk as the
 
4826
      old data and index files.  Create also symlinks to point at
 
4827
      the new tables.
 
4828
      Copy data.
 
4829
      At end, rename intermediate tables, and symlinks to intermediate
 
4830
      table, to final table name.
 
4831
      Remove old table and old symlinks
 
4832
 
 
4833
    If rename is made to another database:
 
4834
      Create new tables in new database.
 
4835
      Copy data.
 
4836
      Remove old table and symlinks.
 
4837
  */
 
4838
  if (db_changed)               // Ignore symlink if db changed
 
4839
  {
 
4840
    if (create_info->index_file_name)
 
4841
    {
 
4842
      /* Fix index_file_name to have 'tmp_name' as basename */
 
4843
      strmov(index_file, tmp_name);
 
4844
      create_info->index_file_name=fn_same(index_file,
 
4845
                                           create_info->index_file_name,
 
4846
                                           1);
 
4847
    }
 
4848
    if (create_info->data_file_name)
 
4849
    {
 
4850
      /* Fix data_file_name to have 'tmp_name' as basename */
 
4851
      strmov(data_file, tmp_name);
 
4852
      create_info->data_file_name=fn_same(data_file,
 
4853
                                          create_info->data_file_name,
 
4854
                                          1);
 
4855
    }
 
4856
  }
 
4857
  else
 
4858
    create_info->data_file_name=create_info->index_file_name=0;
 
4859
 
 
4860
  if (new_db_type == old_db_type)
 
4861
  {
 
4862
    /*
 
4863
       Table has not changed storage engine.
 
4864
       If STORAGE and TABLESPACE have not been changed than copy them
 
4865
       from the original table
 
4866
    */
 
4867
    if (!create_info->tablespace &&
 
4868
        table->s->tablespace &&
 
4869
        create_info->default_storage_media == HA_SM_DEFAULT)
 
4870
      create_info->tablespace= table->s->tablespace;
 
4871
    if (create_info->default_storage_media == HA_SM_DEFAULT)
 
4872
      create_info->default_storage_media= table->s->default_storage_media;
 
4873
   }
 
4874
 
 
4875
  /*
 
4876
    Create a table with a temporary name.
 
4877
    With create_info->frm_only == 1 this creates a .frm file only.
 
4878
    We don't log the statement, it will be logged later.
 
4879
  */
 
4880
  tmp_disable_binlog(thd);
 
4881
  error= mysql_create_table(thd, new_db, tmp_name,
 
4882
                            create_info, alter_info, 1, 0);
 
4883
  reenable_binlog(thd);
 
4884
 
 
4885
  DBUG_RETURN(error);
 
4886
}
 
4887
 
 
4888
/*
 
4889
  Create a temporary table that reflects what an alter table operation
 
4890
  will accomplish.
 
4891
 
 
4892
  SYNOPSIS
 
4893
    create_altered_table()
 
4894
      thd              Thread handle
 
4895
      table            The original table
 
4896
      create_info      Information from the parsing phase about new
 
4897
                       table properties.
 
4898
      alter_info       Lists of fields, keys to be changed, added
 
4899
                       or dropped.
 
4900
      db_change        Specifies if the table is moved to another database
 
4901
  RETURN
 
4902
    A temporary table with all changes
 
4903
    NULL if error
 
4904
  NOTES
 
4905
    The temporary table is created without storing it in any storage engine
 
4906
    and is opened only to get the table struct and frm file reference.
 
4907
*/
 
4908
TABLE *create_altered_table(THD *thd,
 
4909
                            TABLE *table,
 
4910
                            char *new_db,
 
4911
                            HA_CREATE_INFO *create_info,
 
4912
                            Alter_info *alter_info,
 
4913
                            bool db_change)
 
4914
{
 
4915
  int error;
 
4916
  HA_CREATE_INFO altered_create_info(*create_info);
 
4917
  TABLE *altered_table;
 
4918
  char tmp_name[80];
 
4919
  char path[FN_REFLEN];
 
4920
  DBUG_ENTER("create_altered_table");
 
4921
 
 
4922
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
 
4923
           tmp_file_prefix, current_pid, thd->thread_id);
 
4924
  /* Safety fix for InnoDB */
 
4925
  if (lower_case_table_names)
 
4926
    my_casedn_str(files_charset_info, tmp_name);
 
4927
  altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
 
4928
  altered_create_info.frm_only= 1;
 
4929
  if ((error= create_temporary_table(thd, table, new_db, tmp_name,
 
4930
                                     &altered_create_info,
 
4931
                                     alter_info, db_change)))
 
4932
  {
 
4933
    DBUG_PRINT("info", ("Error %u while creating temporary table", error));
 
4934
    DBUG_RETURN(NULL);
 
4935
  };
 
4936
 
 
4937
  build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
4938
                       FN_IS_TMP);
 
4939
  altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
 
4940
                                      OTM_ALTER);
 
4941
  DBUG_RETURN(altered_table);
 
4942
 
 
4943
  DBUG_RETURN(NULL);
 
4944
}
 
4945
 
 
4946
 
 
4947
/*
 
4948
  Perform a fast or on-line alter table
 
4949
 
 
4950
  SYNOPSIS
 
4951
    mysql_fast_or_online_alter_table()
 
4952
      thd              Thread handle
 
4953
      table            The original table
 
4954
      altered_table    A temporary table showing how we will change table
 
4955
      create_info      Information from the parsing phase about new
 
4956
                       table properties.
 
4957
      alter_info       Storage place for data used during different phases
 
4958
      ha_alter_flags   Bitmask that shows what will be changed
 
4959
      keys_onoff       Specifies if keys are to be enabled/disabled
 
4960
  RETURN
 
4961
     0  OK
 
4962
    >0  An error occured during the on-line alter table operation
 
4963
    -1  Error when re-opening table
 
4964
  NOTES
 
4965
    If mysql_alter_table does not need to copy the table, it is
 
4966
    either a fast alter table where the storage engine does not
 
4967
    need to know about the change, only the frm will change,
 
4968
    or the storage engine supports performing the alter table
 
4969
    operation directly, on-line without mysql having to copy
 
4970
    the table.
 
4971
*/
 
4972
int mysql_fast_or_online_alter_table(THD *thd,
 
4973
                                     TABLE *table,
 
4974
                                     TABLE *altered_table,
 
4975
                                     HA_CREATE_INFO *create_info,
 
4976
                                     HA_ALTER_INFO *alter_info,
 
4977
                                     HA_ALTER_FLAGS *ha_alter_flags,
 
4978
                                     enum enum_enable_or_disable keys_onoff)
 
4979
{
 
4980
  int error= 0;
 
4981
  bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
 
4982
  TABLE *t_table;
 
4983
 
 
4984
  DBUG_ENTER(" mysql_fast_or_online_alter_table");
 
4985
  if (online)
 
4986
  {
 
4987
   /*
 
4988
      Tell the handler to prepare for the online alter
 
4989
    */
 
4990
    if ((error= table->file->alter_table_phase1(thd,
 
4991
                                                altered_table,
 
4992
                                                create_info,
 
4993
                                                alter_info,
 
4994
                                                ha_alter_flags)))
 
4995
    {
 
4996
      goto err;
 
4997
    }
 
4998
 
 
4999
    /*
 
5000
       Tell the storage engine to perform the online alter table
 
5001
       TODO: 
 
5002
       if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
 
5003
       we need to wrap the next call with a DDL lock.
 
5004
     */
 
5005
    if ((error= table->file->alter_table_phase2(thd,
 
5006
                                                altered_table,
 
5007
                                                create_info,
 
5008
                                                alter_info,
 
5009
                                                ha_alter_flags)))
 
5010
    {
 
5011
      goto err;
 
5012
    }
 
5013
  }
 
5014
  /*
 
5015
    The final .frm file is already created as a temporary file
 
5016
    and will be renamed to the original table name.
 
5017
  */
 
5018
  VOID(pthread_mutex_lock(&LOCK_open));
 
5019
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
5020
  alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
5021
                          keys_onoff);
 
5022
  close_data_files_and_morph_locks(thd,
 
5023
                                   table->pos_in_table_list->db,
 
5024
                                   table->pos_in_table_list->table_name);
 
5025
  if (mysql_rename_table(NULL,
 
5026
                         altered_table->s->db.str,
 
5027
                         altered_table->s->table_name.str,
 
5028
                         table->s->db.str,
 
5029
                         table->s->table_name.str, FN_FROM_IS_TMP))
 
5030
  {
 
5031
    error= 1;
 
5032
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5033
    goto err;
 
5034
  }
 
5035
  broadcast_refresh();
 
5036
  VOID(pthread_mutex_unlock(&LOCK_open));
 
5037
 
 
5038
  /*
 
5039
    The ALTER TABLE is always in its own transaction.
 
5040
    Commit must not be called while LOCK_open is locked. It could call
 
5041
    wait_if_global_read_lock(), which could create a deadlock if called
 
5042
    with LOCK_open.
 
5043
  */
 
5044
  error= ha_autocommit_or_rollback(thd, 0);
 
5045
 
 
5046
  if (ha_commit(thd))
 
5047
    error=1;
 
5048
  if (error)
 
5049
    goto err;
 
5050
  if (online)
 
5051
  {
 
5052
    VOID(pthread_mutex_lock(&LOCK_open));
 
5053
    if (reopen_table(table))
 
5054
    {
 
5055
      error= -1;
 
5056
      goto err;
 
5057
    }
 
5058
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5059
    t_table= table;
 
5060
 
 
5061
   /*
 
5062
      Tell the handler that the changed frm is on disk and table
 
5063
      has been re-opened
 
5064
   */
 
5065
    if ((error= t_table->file->alter_table_phase3(thd, t_table)))
 
5066
    {
 
5067
      goto err;
 
5068
    }
 
5069
 
 
5070
    /*
 
5071
      We are going to reopen table down on the road, so we have to restore
 
5072
      state of the TABLE object which we used for obtaining of handler
 
5073
      object to make it suitable for reopening.
 
5074
    */
 
5075
    DBUG_ASSERT(t_table == table);
 
5076
    table->open_placeholder= 1;
 
5077
    VOID(pthread_mutex_lock(&LOCK_open));
 
5078
    close_handle_and_leave_table_as_lock(table);
 
5079
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5080
  }
 
5081
 
 
5082
 err:
 
5083
  if (error)
 
5084
    DBUG_PRINT("info", ("Got error %u", error));
 
5085
  DBUG_RETURN(error);
 
5086
}
 
5087
 
 
5088
 
 
5089
/**
 
5090
  Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
 
5091
 
 
5092
  This function transforms parse output of ALTER TABLE - lists of
 
5093
  columns and keys to add, drop or modify into, essentially,
 
5094
  CREATE TABLE definition - a list of columns and keys of the new
 
5095
  table. While doing so, it also performs some (bug not all)
 
5096
  semantic checks.
 
5097
 
 
5098
  This function is invoked when we know that we're going to
 
5099
  perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
 
5100
  is not possible, perhaps because the ALTER statement contains
 
5101
  instructions that require change in table data, not only in
 
5102
  table definition or indexes.
 
5103
 
 
5104
  @param[in,out]  thd         thread handle. Used as a memory pool
 
5105
                              and source of environment information.
 
5106
  @param[in]      table       the source table, open and locked
 
5107
                              Used as an interface to the storage engine
 
5108
                              to acquire additional information about
 
5109
                              the original table.
 
5110
  @param[in,out]  create_info A blob with CREATE/ALTER TABLE
 
5111
                              parameters
 
5112
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
 
5113
                              Originally create_info was used only in
 
5114
                              CREATE TABLE and alter_info only in ALTER TABLE.
 
5115
                              But since ALTER might end-up doing CREATE,
 
5116
                              this distinction is gone and we just carry
 
5117
                              around two structures.
 
5118
 
 
5119
  @return
 
5120
    Fills various create_info members based on information retrieved
 
5121
    from the storage engine.
 
5122
    Sets create_info->varchar if the table has a VARCHAR column.
 
5123
    Prepares alter_info->create_list and alter_info->key_list with
 
5124
    columns and keys of the new table.
 
5125
  @retval true   error, out of memory or a semantical error in ALTER
 
5126
                 TABLE instructions
 
5127
  @retval false  success
 
5128
*/
 
5129
 
 
5130
static bool
 
5131
mysql_prepare_alter_table(THD *thd, TABLE *table,
 
5132
                          HA_CREATE_INFO *create_info,
 
5133
                          Alter_info *alter_info)
 
5134
{
 
5135
  /* New column definitions are added here */
 
5136
  List<Create_field> new_create_list;
 
5137
  /* New key definitions are added here */
 
5138
  List<Key> new_key_list;
 
5139
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
 
5140
  List_iterator<Create_field> def_it(alter_info->create_list);
 
5141
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
 
5142
  List_iterator<Key> key_it(alter_info->key_list);
 
5143
  List_iterator<Create_field> find_it(new_create_list);
 
5144
  List_iterator<Create_field> field_it(new_create_list);
 
5145
  List<Key_part_spec> key_parts;
 
5146
  uint db_create_options= (table->s->db_create_options
 
5147
                           & ~(HA_OPTION_PACK_RECORD));
 
5148
  uint used_fields= create_info->used_fields;
 
5149
  KEY *key_info=table->key_info;
 
5150
  bool rc= true;
 
5151
 
 
5152
  DBUG_ENTER("mysql_prepare_alter_table");
 
5153
 
 
5154
  create_info->varchar= false;
 
5155
  /* Let new create options override the old ones */
 
5156
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
 
5157
    create_info->min_rows= table->s->min_rows;
 
5158
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
 
5159
    create_info->max_rows= table->s->max_rows;
 
5160
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
 
5161
    create_info->avg_row_length= table->s->avg_row_length;
 
5162
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
5163
    create_info->default_table_charset= table->s->table_charset;
 
5164
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
5165
    {
 
5166
    /* Table has an autoincrement, copy value to new table */
 
5167
    table->file->info(HA_STATUS_AUTO);
 
5168
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
 
5169
  }
 
5170
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
5171
    create_info->key_block_size= table->s->key_block_size;
 
5172
  if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
 
5173
    create_info->transactional= table->s->transactional;
 
5174
 
 
5175
  restore_record(table, s->default_values);     // Empty record for DEFAULT
 
5176
  Create_field *def;
 
5177
 
 
5178
    /*
 
5179
    First collect all fields from table which isn't in drop_list
 
5180
    */
 
5181
  Field **f_ptr,*field;
 
5182
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
 
5183
    {
 
5184
    if (field->type() == MYSQL_TYPE_STRING)
 
5185
      create_info->varchar= true;
 
5186
    /* Check if field should be dropped */
 
5187
    Alter_drop *drop;
 
5188
    drop_it.rewind();
 
5189
    while ((drop=drop_it++))
 
5190
    {
 
5191
      if (drop->type == Alter_drop::COLUMN &&
 
5192
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
 
5193
    {
 
5194
        /* Reset auto_increment value if it was dropped */
 
5195
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
5196
            !(used_fields & HA_CREATE_USED_AUTO))
 
5197
      {
 
5198
          create_info->auto_increment_value=0;
 
5199
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
5200
      }
 
5201
        break;
 
5202
    }
 
5203
  }
 
5204
    if (drop)
 
5205
      {
 
5206
      drop_it.remove();
 
5207
      continue;
 
5208
    }
 
5209
    /* Check if field is changed */
 
5210
    def_it.rewind();
 
5211
    while ((def=def_it++))
 
5212
    {
 
5213
      if (def->change &&
 
5214
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
5215
        break;
 
5216
    }
 
5217
    if (def)
 
5218
    {                                           // Field is changed
 
5219
      def->field=field;
 
5220
      if (!def->after)
 
5221
        {
 
5222
        new_create_list.push_back(def);
 
5223
        def_it.remove();
 
5224
        }
 
5225
      }
 
5226
      else
 
5227
      {
 
5228
      /*
 
5229
        This field was not dropped and not changed, add it to the list
 
5230
        for the new table.
 
5231
      */
 
5232
      def= new Create_field(field, field);
 
5233
      new_create_list.push_back(def);
 
5234
      alter_it.rewind();                        // Change default if ALTER
 
5235
      Alter_column *alter;
 
5236
      while ((alter=alter_it++))
 
5237
        {
 
5238
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
5239
          break;
 
5240
        }
 
5241
      if (alter)
 
5242
        {
 
5243
        if (def->sql_type == MYSQL_TYPE_BLOB)
 
5244
        {
 
5245
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
5246
          goto err;
 
5247
        }
 
5248
        if ((def->def=alter->def))              // Use new default
 
5249
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
 
5250
        else
 
5251
          def->flags|= NO_DEFAULT_VALUE_FLAG;
 
5252
        alter_it.remove();
 
5253
      }
 
5254
    }
 
5255
  }
 
5256
  def_it.rewind();
 
5257
  while ((def=def_it++))                        // Add new columns
 
5258
  {
 
5259
    if (def->change && ! def->field)
 
5260
    {
 
5261
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
5262
      goto err;
 
5263
    }
 
5264
      /*
 
5265
      Check that the DATE/DATETIME not null field we are going to add is
 
5266
      either has a default value or the '0000-00-00' is allowed by the
 
5267
      set sql mode.
 
5268
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
5269
      flag to allow ALTER TABLE only if the table to be altered is empty.
 
5270
      */
 
5271
    if ((def->sql_type == MYSQL_TYPE_NEWDATE ||
 
5272
         def->sql_type == MYSQL_TYPE_DATETIME) &&
 
5273
         !alter_info->datetime_field &&
 
5274
         !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
5275
         thd->variables.sql_mode & MODE_NO_ZERO_DATE)
 
5276
    {
 
5277
        alter_info->datetime_field= def;
 
5278
        alter_info->error_if_not_empty= true;
 
5279
    }
 
5280
    if (!def->after)
 
5281
      new_create_list.push_back(def);
 
5282
    else if (def->after == first_keyword)
 
5283
      new_create_list.push_front(def);
 
5284
    else
 
5285
    {
 
5286
      Create_field *find;
 
5287
      find_it.rewind();
 
5288
      while ((find=find_it++))                  // Add new columns
 
5289
      {
 
5290
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
5291
          break;
 
5292
  }
 
5293
      if (!find)
 
5294
  {
 
5295
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
5296
    goto err;
 
5297
  }
 
5298
      find_it.after(def);                       // Put element after this
 
5299
      /*
 
5300
        XXX: hack for Bug#28427.
 
5301
        If column order has changed, force OFFLINE ALTER TABLE
 
5302
        without querying engine capabilities.  If we ever have an
 
5303
        engine that supports online ALTER TABLE CHANGE COLUMN
 
5304
        <name> AFTER <name1> (Falcon?), this fix will effectively
 
5305
        disable the capability.
 
5306
        TODO: detect the situation in compare_tables, behave based
 
5307
        on engine capabilities.
 
5308
      */
 
5309
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
5310
      {
 
5311
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
5312
        goto err;
 
5313
      }
 
5314
      alter_info->build_method= HA_BUILD_OFFLINE;
 
5315
    }
 
5316
  }
 
5317
  if (alter_info->alter_list.elements)
 
5318
  {
 
5319
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
5320
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
5321
    goto err;
 
5322
    }
 
5323
  if (!new_create_list.elements)
 
5324
    {
 
5325
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
 
5326
               MYF(0));
 
5327
    goto err;
 
5328
    }
 
5329
 
 
5330
    /*
 
5331
    Collect all keys which isn't in drop list. Add only those
 
5332
    for which some fields exists.
 
5333
    */
 
5334
 
 
5335
  for (uint i=0 ; i < table->s->keys ; i++,key_info++)
 
5336
    {
 
5337
    char *key_name= key_info->name;
 
5338
    Alter_drop *drop;
 
5339
    drop_it.rewind();
 
5340
    while ((drop=drop_it++))
 
5341
      {
 
5342
      if (drop->type == Alter_drop::KEY &&
 
5343
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
5344
        break;
 
5345
      }
 
5346
    if (drop)
 
5347
        {
 
5348
      drop_it.remove();
 
5349
      continue;
 
5350
    }
 
5351
 
 
5352
    KEY_PART_INFO *key_part= key_info->key_part;
 
5353
    key_parts.empty();
 
5354
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
5355
    {
 
5356
      if (!key_part->field)
 
5357
        continue;                               // Wrong field (from UNIREG)
 
5358
      const char *key_part_name=key_part->field->field_name;
 
5359
      Create_field *cfield;
 
5360
      field_it.rewind();
 
5361
      while ((cfield=field_it++))
 
5362
    {
 
5363
        if (cfield->change)
 
5364
    {
 
5365
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
5366
                             cfield->change))
 
5367
            break;
 
5368
        }
 
5369
        else if (!my_strcasecmp(system_charset_info,
 
5370
                                key_part_name, cfield->field_name))
 
5371
          break;
 
5372
      }
 
5373
      if (!cfield)
 
5374
        continue;                               // Field is removed
 
5375
      uint key_part_length=key_part->length;
 
5376
      if (cfield->field)                        // Not new field
 
5377
      {
 
5378
        /*
 
5379
          If the field can't have only a part used in a key according to its
 
5380
          new type, or should not be used partially according to its
 
5381
          previous type, or the field length is less than the key part
 
5382
          length, unset the key part length.
 
5383
 
 
5384
          We also unset the key part length if it is the same as the
 
5385
          old field's length, so the whole new field will be used.
 
5386
 
 
5387
          BLOBs may have cfield->length == 0, which is why we test it before
 
5388
          checking whether cfield->length < key_part_length (in chars).
 
5389
         */
 
5390
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
5391
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
5392
            (cfield->field->field_length == key_part_length &&
 
5393
             !f_is_blob(key_part->key_type)) ||
 
5394
            (cfield->length && (cfield->length < key_part_length /
 
5395
                                key_part->field->charset()->mbmaxlen)))
 
5396
          key_part_length= 0;                   // Use whole field
 
5397
      }
 
5398
      key_part_length /= key_part->field->charset()->mbmaxlen;
 
5399
      key_parts.push_back(new Key_part_spec(cfield->field_name,
 
5400
                                            strlen(cfield->field_name),
 
5401
                                            key_part_length));
 
5402
    }
 
5403
    if (key_parts.elements)
 
5404
    {
 
5405
      KEY_CREATE_INFO key_create_info;
 
5406
      Key *key;
 
5407
      enum Key::Keytype key_type;
 
5408
      bzero((char*) &key_create_info, sizeof(key_create_info));
 
5409
 
 
5410
      key_create_info.algorithm= key_info->algorithm;
 
5411
      if (key_info->flags & HA_USES_BLOCK_SIZE)
 
5412
        key_create_info.block_size= key_info->block_size;
 
5413
      if (key_info->flags & HA_USES_COMMENT)
 
5414
        key_create_info.comment= key_info->comment;
 
5415
 
 
5416
      if (key_info->flags & HA_NOSAME)
 
5417
      {
 
5418
        if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
 
5419
          key_type= Key::PRIMARY;
 
5420
        else
 
5421
          key_type= Key::UNIQUE;
 
5422
      }
 
5423
      else
 
5424
        key_type= Key::MULTIPLE;
 
5425
 
 
5426
      key= new Key(key_type, key_name, strlen(key_name),
 
5427
                   &key_create_info,
 
5428
                   test(key_info->flags & HA_GENERATED_KEY),
 
5429
                   key_parts);
 
5430
      new_key_list.push_back(key);
 
5431
    }
 
5432
  }
 
5433
  {
 
5434
    Key *key;
 
5435
    while ((key=key_it++))                      // Add new keys
 
5436
    {
 
5437
      if (key->type != Key::FOREIGN_KEY)
 
5438
        new_key_list.push_back(key);
 
5439
      if (key->name.str &&
 
5440
          !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
 
5441
      {
 
5442
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
5443
        goto err;
 
5444
      }
 
5445
    }
 
5446
  }
 
5447
 
 
5448
  if (alter_info->drop_list.elements)
 
5449
  {
 
5450
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
5451
             alter_info->drop_list.head()->name);
 
5452
    goto err;
 
5453
  }
 
5454
  if (alter_info->alter_list.elements)
 
5455
  {
 
5456
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
5457
             alter_info->alter_list.head()->name);
 
5458
    goto err;
 
5459
  }
 
5460
 
 
5461
  if (!create_info->comment.str)
 
5462
  {
 
5463
    create_info->comment.str= table->s->comment.str;
 
5464
    create_info->comment.length= table->s->comment.length;
 
5465
  }
 
5466
 
 
5467
  table->file->update_create_info(create_info);
 
5468
  if ((create_info->table_options &
 
5469
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
 
5470
      (used_fields & HA_CREATE_USED_PACK_KEYS))
 
5471
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
 
5472
  if (create_info->table_options &
 
5473
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
 
5474
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
 
5475
  if (create_info->table_options &
 
5476
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
 
5477
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
 
5478
                          HA_OPTION_NO_DELAY_KEY_WRITE);
 
5479
  create_info->table_options|= db_create_options;
 
5480
 
 
5481
  if (table->s->tmp_table)
 
5482
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
5483
 
 
5484
  rc= false;
 
5485
  alter_info->create_list.swap(new_create_list);
 
5486
  alter_info->key_list.swap(new_key_list);
 
5487
err:
 
5488
  DBUG_RETURN(rc);
 
5489
}
 
5490
 
 
5491
 
 
5492
/*
 
5493
  Alter table
 
5494
 
 
5495
  SYNOPSIS
 
5496
    mysql_alter_table()
 
5497
      thd              Thread handle
 
5498
      new_db           If there is a RENAME clause
 
5499
      new_name         If there is a RENAME clause
 
5500
      create_info      Information from the parsing phase about new
 
5501
                       table properties.
 
5502
      table_list       The table to change.
 
5503
      alter_info       Lists of fields, keys to be changed, added
 
5504
                       or dropped.
 
5505
      order_num        How many ORDER BY fields has been specified.
 
5506
      order            List of fields to ORDER BY.
 
5507
      ignore           Whether we have ALTER IGNORE TABLE
 
5508
 
 
5509
  DESCRIPTION
 
5510
    This is a veery long function and is everything but the kitchen sink :)
 
5511
    It is used to alter a table and not only by ALTER TABLE but also
 
5512
    CREATE|DROP INDEX are mapped on this function.
 
5513
 
 
5514
    When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
 
5515
    or both, then this function short cuts its operation by renaming
 
5516
    the table and/or enabling/disabling the keys. In this case, the FRM is
 
5517
    not changed, directly by mysql_alter_table. However, if there is a
 
5518
    RENAME + change of a field, or an index, the short cut is not used.
 
5519
    See how `create_list` is used to generate the new FRM regarding the
 
5520
    structure of the fields. The same is done for the indices of the table.
 
5521
 
 
5522
    Important is the fact, that this function tries to do as little work as
 
5523
    possible, by finding out whether a intermediate table is needed to copy
 
5524
    data into and when finishing the altering to use it as the original table.
 
5525
    For this reason the function compare_tables() is called, which decides
 
5526
    based on all kind of data how similar are the new and the original
 
5527
    tables.
 
5528
 
 
5529
  RETURN VALUES
 
5530
    false  OK
 
5531
    true   Error
 
5532
*/
 
5533
 
 
5534
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
 
5535
                       HA_CREATE_INFO *create_info,
 
5536
                       TABLE_LIST *table_list,
 
5537
                       Alter_info *alter_info,
 
5538
                       uint order_num, ORDER *order, bool ignore)
 
5539
{
 
5540
  TABLE *table, *new_table=0, *name_lock= 0;;
 
5541
  int error= 0;
 
5542
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
 
5543
  char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
 
5544
  char path[FN_REFLEN];
 
5545
  ha_rows copied= 0,deleted= 0;
 
5546
  handlerton *old_db_type, *new_db_type, *save_old_db_type;
 
5547
  legacy_db_type table_type;
 
5548
  frm_type_enum frm_type;
 
5549
  DBUG_ENTER("mysql_alter_table");
 
5550
 
 
5551
  if (table_list && table_list->schema_table)
 
5552
  {
 
5553
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
5554
    DBUG_RETURN(true);
 
5555
  }
 
5556
 
 
5557
  /*
 
5558
    Assign variables table_name, new_name, db, new_db, path
 
5559
    to simplify further comparisons: we want to see if it's a RENAME
 
5560
    later just by comparing the pointers, avoiding the need for strcmp.
 
5561
  */
 
5562
  thd_proc_info(thd, "init");
 
5563
  table_name=table_list->table_name;
 
5564
  alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
 
5565
  db=table_list->db;
 
5566
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
 
5567
    new_db= db;
 
5568
  build_table_filename(path, sizeof(path), db, table_name, "", 0);
 
5569
 
 
5570
  mysql_ha_rm_tables(thd, table_list, false);
 
5571
 
 
5572
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
 
5573
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
5574
    /* Conditionally writes to binlog. */
 
5575
    DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
 
5576
                                                   alter_info->tablespace_op));
 
5577
  strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, 
 
5578
           "/", table_name, reg_ext, NullS);
 
5579
  (void) unpack_filename(new_name_buff, new_name_buff);
 
5580
  /*
 
5581
    If this is just a rename of a view, short cut to the
 
5582
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
5583
    2) unlock LOCK_open.
 
5584
    This is a copy-paste added to make sure
 
5585
    ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
 
5586
    as an independent branch in mysql_execute_command. The need
 
5587
    for a copy-paste arose because the main code flow of ALTER TABLE
 
5588
    ... RENAME tries to use open_ltable, which does not work for views
 
5589
    (open_ltable was never modified to merge table lists of child tables
 
5590
    into the main table list, like open_tables does).
 
5591
    This code is wrong and will be removed, please do not copy.
 
5592
  */
 
5593
  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
 
5594
 
 
5595
  if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
 
5596
    DBUG_RETURN(true);
 
5597
  table->use_all_columns();
 
5598
 
 
5599
  /*
 
5600
    Prohibit changing of the UNION list of a non-temporary MERGE table
 
5601
    under LOCK tables. It would be quite difficult to reuse a shrinked
 
5602
    set of tables from the old table or to open a new TABLE object for
 
5603
    an extended list and verify that they belong to locked tables.
 
5604
  */
 
5605
  if (thd->locked_tables &&
 
5606
      (create_info->used_fields & HA_CREATE_USED_UNION) &&
 
5607
      (table->s->tmp_table == NO_TMP_TABLE))
 
5608
  {
 
5609
    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
 
5610
    DBUG_RETURN(true);
 
5611
  }
 
5612
 
 
5613
  /* Check that we are not trying to rename to an existing table */
 
5614
  if (new_name)
 
5615
  {
 
5616
    DBUG_PRINT("info", ("new_db.new_name: '%s'.'%s'", new_db, new_name));
 
5617
    strmov(new_name_buff,new_name);
 
5618
    strmov(new_alias= new_alias_buff, new_name);
 
5619
    if (lower_case_table_names)
 
5620
    {
 
5621
      if (lower_case_table_names != 2)
 
5622
      {
 
5623
        my_casedn_str(files_charset_info, new_name_buff);
 
5624
        new_alias= new_name;                    // Create lower case table name
 
5625
      }
 
5626
      my_casedn_str(files_charset_info, new_name);
 
5627
    }
 
5628
    if (new_db == db &&
 
5629
        !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
5630
    {
 
5631
      /*
 
5632
        Source and destination table names are equal: make later check
 
5633
        easier.
 
5634
      */
 
5635
      new_alias= new_name= table_name;
 
5636
    }
 
5637
    else
 
5638
    {
 
5639
      if (table->s->tmp_table != NO_TMP_TABLE)
 
5640
      {
 
5641
        if (find_temporary_table(thd,new_db,new_name_buff))
 
5642
        {
 
5643
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
5644
          DBUG_RETURN(true);
 
5645
        }
 
5646
      }
 
5647
      else
 
5648
      {
 
5649
        if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
 
5650
          DBUG_RETURN(true);
 
5651
        if (!name_lock)
 
5652
        {
 
5653
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
5654
          DBUG_RETURN(true);
 
5655
        }
 
5656
 
 
5657
        build_table_filename(new_name_buff, sizeof(new_name_buff),
 
5658
                             new_db, new_name_buff, reg_ext, 0);
 
5659
        if (!access(new_name_buff, F_OK))
 
5660
        {
 
5661
          /* Table will be closed in do_command() */
 
5662
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
5663
          goto err;
 
5664
        }
 
5665
      }
 
5666
    }
 
5667
  }
 
5668
  else
 
5669
  {
 
5670
    new_alias= (lower_case_table_names == 2) ? alias : table_name;
 
5671
    new_name= table_name;
 
5672
  }
 
5673
 
 
5674
  old_db_type= table->s->db_type();
 
5675
  if (!create_info->db_type)
 
5676
  {
 
5677
    create_info->db_type= old_db_type;
 
5678
  }
 
5679
 
 
5680
  if (check_engine(thd, new_name, create_info))
 
5681
    goto err;
 
5682
  new_db_type= create_info->db_type;
 
5683
 
 
5684
  if (new_db_type != old_db_type ||
 
5685
      !table->file->can_switch_engines())
 
5686
  {
 
5687
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
 
5688
    goto err;
 
5689
  }
 
5690
 
 
5691
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
5692
    create_info->row_type= table->s->row_type;
 
5693
 
 
5694
  DBUG_PRINT("info", ("old type: %s  new type: %s",
 
5695
             ha_resolve_storage_engine_name(old_db_type),
 
5696
             ha_resolve_storage_engine_name(new_db_type)));
 
5697
  if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
 
5698
      ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
 
5699
  {
 
5700
    DBUG_PRINT("info", ("doesn't support alter"));
 
5701
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
5702
    goto err;
 
5703
  }
 
5704
 
 
5705
  thd_proc_info(thd, "setup");
 
5706
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
 
5707
      !table->s->tmp_table) // no need to touch frm
 
5708
  {
 
5709
    switch (alter_info->keys_onoff) {
 
5710
    case LEAVE_AS_IS:
 
5711
      break;
 
5712
    case ENABLE:
 
5713
      /*
 
5714
        wait_while_table_is_used() ensures that table being altered is
 
5715
        opened only by this thread and that TABLE::TABLE_SHARE::version
 
5716
        of TABLE object corresponding to this table is 0.
 
5717
        The latter guarantees that no DML statement will open this table
 
5718
        until ALTER TABLE finishes (i.e. until close_thread_tables())
 
5719
        while the fact that the table is still open gives us protection
 
5720
        from concurrent DDL statements.
 
5721
      */
 
5722
      VOID(pthread_mutex_lock(&LOCK_open));
 
5723
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
5724
      VOID(pthread_mutex_unlock(&LOCK_open));
 
5725
      DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
 
5726
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
5727
      /* COND_refresh will be signaled in close_thread_tables() */
 
5728
      break;
 
5729
    case DISABLE:
 
5730
      VOID(pthread_mutex_lock(&LOCK_open));
 
5731
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
5732
      VOID(pthread_mutex_unlock(&LOCK_open));
 
5733
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
5734
      /* COND_refresh will be signaled in close_thread_tables() */
 
5735
      break;
 
5736
    default:
 
5737
      DBUG_ASSERT(false);
 
5738
      error= 0;
 
5739
      break;
 
5740
    }
 
5741
    if (error == HA_ERR_WRONG_COMMAND)
 
5742
    {
 
5743
      error= 0;
 
5744
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
5745
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
5746
                          table->alias);
 
5747
    }
 
5748
 
 
5749
    VOID(pthread_mutex_lock(&LOCK_open));
 
5750
    /*
 
5751
      Unlike to the above case close_cached_table() below will remove ALL
 
5752
      instances of TABLE from table cache (it will also remove table lock
 
5753
      held by this thread). So to make actual table renaming and writing
 
5754
      to binlog atomic we have to put them into the same critical section
 
5755
      protected by LOCK_open mutex. This also removes gap for races between
 
5756
      access() and mysql_rename_table() calls.
 
5757
    */
 
5758
 
 
5759
    if (!error && (new_name != table_name || new_db != db))
 
5760
    {
 
5761
      thd_proc_info(thd, "rename");
 
5762
      /*
 
5763
        Then do a 'simple' rename of the table. First we need to close all
 
5764
        instances of 'source' table.
 
5765
      */
 
5766
      close_cached_table(thd, table);
 
5767
      /*
 
5768
        Then, we want check once again that target table does not exist.
 
5769
        Actually the order of these two steps does not matter since
 
5770
        earlier we took name-lock on the target table, so we do them
 
5771
        in this particular order only to be consistent with 5.0, in which
 
5772
        we don't take this name-lock and where this order really matters.
 
5773
        TODO: Investigate if we need this access() check at all.
 
5774
      */
 
5775
      if (!access(new_name_buff,F_OK))
 
5776
      {
 
5777
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
5778
        error= -1;
 
5779
      }
 
5780
      else
 
5781
      {
 
5782
        *fn_ext(new_name)=0;
 
5783
        if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
 
5784
          error= -1;
 
5785
        else if (0)
 
5786
      {
 
5787
          VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
 
5788
                                  table_name, 0));
 
5789
          error= -1;
 
5790
      }
 
5791
    }
 
5792
  }
 
5793
 
 
5794
    if (error == HA_ERR_WRONG_COMMAND)
 
5795
  {
 
5796
      error= 0;
 
5797
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
5798
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
5799
                          table->alias);
 
5800
  }
 
5801
 
 
5802
    if (!error)
 
5803
    {
 
5804
      write_bin_log(thd, true, thd->query, thd->query_length);
 
5805
      my_ok(thd);
 
5806
  }
 
5807
    else if (error > 0)
 
5808
  {
 
5809
      table->file->print_error(error, MYF(0));
 
5810
      error= -1;
 
5811
    }
2178
5812
    if (name_lock)
2179
 
    {
2180
 
      boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2181
 
      session->unlink_open_table(name_lock);
2182
 
    }
2183
 
  }
2184
 
 
2185
 
  if (table_exists)
2186
 
  {
2187
 
    if (is_if_not_exists)
2188
 
    {
2189
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2190
 
      snprintf(warn_buff, sizeof(warn_buff),
2191
 
               ER(ER_TABLE_EXISTS_ERROR), table_name);
2192
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2193
 
                   ER_TABLE_EXISTS_ERROR,warn_buff);
2194
 
      res= false;
2195
 
    }
2196
 
    else
2197
 
    {
2198
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2199
 
    }
2200
 
  }
2201
 
 
2202
 
  return(res);
2203
 
}
2204
 
 
2205
 
 
2206
 
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2207
 
{
2208
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2209
 
 
2210
 
  return(mysql_admin_table(session, tables, check_opt,
2211
 
                                "analyze", lock_type, true,
2212
 
                                &Cursor::ha_analyze));
2213
 
}
2214
 
 
2215
 
 
2216
 
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2217
 
{
2218
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2219
 
 
2220
 
  return(mysql_admin_table(session, tables, check_opt,
2221
 
                                "check", lock_type,
2222
 
                                false,
2223
 
                                &Cursor::ha_check));
2224
 
}
2225
 
 
2226
 
} /* namespace drizzled */
 
5813
      unlink_open_table(thd, name_lock, false);
 
5814
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5815
    table_list->table= NULL;                    // For query cache
 
5816
    DBUG_RETURN(error);
 
5817
  }
 
5818
 
 
5819
  /* We have to do full alter table. */
 
5820
 
 
5821
    /*
 
5822
    If the old table had partitions and we are doing ALTER TABLE ...
 
5823
    engine= <new_engine>, the new table must preserve the original
 
5824
    partitioning. That means that the new engine is still the
 
5825
    partitioning engine, not the engine specified in the parser.
 
5826
    This is discovered  in prep_alter_part_table, which in such case
 
5827
    updates create_info->db_type.
 
5828
    Now we need to update the stack copy of create_info->db_type,
 
5829
    as otherwise we won't be able to correctly move the files of the
 
5830
    temporary table to the result table files.
 
5831
  */
 
5832
  new_db_type= create_info->db_type;
 
5833
 
 
5834
  if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
 
5835
      goto err;
 
5836
 
 
5837
  set_table_default_charset(thd, create_info, db);
 
5838
 
 
5839
 
 
5840
  if (thd->variables.old_alter_table
 
5841
      || (table->s->db_type() != create_info->db_type)
 
5842
     )
 
5843
  {
 
5844
    if (alter_info->build_method == HA_BUILD_ONLINE)
 
5845
    {
 
5846
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
5847
      goto err;
 
5848
    }
 
5849
    alter_info->build_method= HA_BUILD_OFFLINE;
 
5850
  }
 
5851
 
 
5852
  if (alter_info->build_method != HA_BUILD_OFFLINE)
 
5853
  {
 
5854
    TABLE *altered_table= 0;
 
5855
    HA_ALTER_INFO ha_alter_info;
 
5856
    HA_ALTER_FLAGS ha_alter_flags;
 
5857
    uint table_changes= IS_EQUAL_YES;
 
5858
    bool need_copy_table= true;
 
5859
    /* Check how much the tables differ. */
 
5860
    if (compare_tables(thd, table, alter_info,
 
5861
                       create_info, order_num,
 
5862
                       &ha_alter_flags,
 
5863
                       &ha_alter_info,
 
5864
                       &table_changes))
 
5865
    {
 
5866
      DBUG_RETURN(true);
 
5867
    }
 
5868
 
 
5869
    /*
 
5870
      Check if storage engine supports altering the table
 
5871
      on-line.
 
5872
    */
 
5873
 
 
5874
#ifndef DBUG_OFF
 
5875
    {
 
5876
      char dbug_string[HA_MAX_ALTER_FLAGS+1];
 
5877
      ha_alter_flags.print(dbug_string);
 
5878
      DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags:  %s",
 
5879
                          need_copy_table, table_changes,
 
5880
                          (char *) dbug_string));
 
5881
    }
 
5882
#endif
 
5883
 
 
5884
    /*
 
5885
      If table is not renamed, changed database and
 
5886
      some change was detected then check if engine
 
5887
      can do the change on-line
 
5888
    */
 
5889
    if (new_name == table_name && new_db == db &&
 
5890
        ha_alter_flags.is_set())
 
5891
    {
 
5892
      Alter_info tmp_alter_info(*alter_info, thd->mem_root);
 
5893
 
 
5894
      /*
 
5895
        If no table rename,
 
5896
        check if table can be altered on-line
 
5897
      */
 
5898
      if (!(altered_table= create_altered_table(thd,
 
5899
                                                table,
 
5900
                                                new_db,
 
5901
                                                create_info,
 
5902
                                                &tmp_alter_info,
 
5903
                                                !strcmp(db, new_db))))
 
5904
        goto err;
 
5905
 
 
5906
      switch (table->file->check_if_supported_alter(altered_table,
 
5907
                                                    create_info,
 
5908
                                                    &ha_alter_flags,
 
5909
                                                    table_changes)) {
 
5910
      case HA_ALTER_SUPPORTED_WAIT_LOCK:
 
5911
      case HA_ALTER_SUPPORTED_NO_LOCK:
 
5912
        /*
 
5913
          @todo: Currently we always acquire an exclusive name
 
5914
          lock on the table metadata when performing fast or online
 
5915
          ALTER TABLE. In future we may consider this unnecessary,
 
5916
          and narrow the scope of the exclusive name lock to only
 
5917
          cover manipulation with .frms. Storage engine API
 
5918
          call check_if_supported_alter has provision for this
 
5919
          already now.
 
5920
        */
 
5921
        need_copy_table= false;
 
5922
        break;
 
5923
      case HA_ALTER_NOT_SUPPORTED:
 
5924
        if (alter_info->build_method == HA_BUILD_ONLINE)
 
5925
        {
 
5926
          my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
5927
          close_temporary_table(thd, altered_table, 1, 1);
 
5928
          goto err;
 
5929
        }
 
5930
        need_copy_table= true;
 
5931
        break;
 
5932
      case HA_ALTER_ERROR:
 
5933
      default:
 
5934
        close_temporary_table(thd, altered_table, 1, 1);
 
5935
        goto err;
 
5936
      }
 
5937
#ifndef DBUG_OFF
 
5938
      {
 
5939
        char dbug_string[HA_MAX_ALTER_FLAGS+1];
 
5940
        ha_alter_flags.print(dbug_string);
 
5941
        DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags:  %s",
 
5942
                            need_copy_table, table_changes,
 
5943
                            (char *) dbug_string));
 
5944
      }
 
5945
#endif
 
5946
 
 
5947
    }
 
5948
    /* TODO need to check if changes can be handled as fast ALTER TABLE */
 
5949
    if (!altered_table)
 
5950
      need_copy_table= true;
 
5951
 
 
5952
    if (!need_copy_table)
 
5953
    {
 
5954
      error= mysql_fast_or_online_alter_table(thd,
 
5955
                                              table,
 
5956
                                              altered_table,
 
5957
                                              create_info,
 
5958
                                              &ha_alter_info,
 
5959
                                              &ha_alter_flags,
 
5960
                                              alter_info->keys_onoff);
 
5961
      if (thd->lock)
 
5962
      {
 
5963
        mysql_unlock_tables(thd, thd->lock);
 
5964
        thd->lock=0;
 
5965
      }
 
5966
      close_temporary_table(thd, altered_table, 1, 1);
 
5967
 
 
5968
      if (error)
 
5969
      {
 
5970
        switch (error) {
 
5971
        case(-1):
 
5972
          goto err_with_placeholders;
 
5973
        default:
 
5974
          goto err;
 
5975
        }
 
5976
      }
 
5977
      else
 
5978
      {
 
5979
        pthread_mutex_lock(&LOCK_open);
 
5980
        goto end_online;
 
5981
      }
 
5982
    }
 
5983
 
 
5984
    if (altered_table)
 
5985
      close_temporary_table(thd, altered_table, 1, 1);
 
5986
  }
 
5987
 
 
5988
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
 
5989
           current_pid, thd->thread_id);
 
5990
  /* Safety fix for innodb */
 
5991
  if (lower_case_table_names)
 
5992
    my_casedn_str(files_charset_info, tmp_name);
 
5993
 
 
5994
 
 
5995
  /* Create a temporary table with the new format */
 
5996
  if ((error= create_temporary_table(thd, table, new_db, tmp_name, 
 
5997
                                     create_info, alter_info, 
 
5998
                                     !strcmp(db, new_db))))
 
5999
  {
 
6000
    goto err;
 
6001
  }
 
6002
 
 
6003
  /* Open the table so we need to copy the data to it. */
 
6004
  if (table->s->tmp_table)
 
6005
  {
 
6006
    TABLE_LIST tbl;
 
6007
    bzero((void*) &tbl, sizeof(tbl));
 
6008
    tbl.db= new_db;
 
6009
    tbl.table_name= tbl.alias= tmp_name;
 
6010
    /* Table is in thd->temporary_tables */
 
6011
    new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
 
6012
                          MYSQL_LOCK_IGNORE_FLUSH);
 
6013
  }
 
6014
  else
 
6015
  {
 
6016
    char path[FN_REFLEN];
 
6017
    /* table is a normal table: Create temporary table in same directory */
 
6018
    build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
6019
                         FN_IS_TMP);
 
6020
    /* Open our intermediate table */
 
6021
    new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
 
6022
  }
 
6023
  if (!new_table)
 
6024
    goto err1;
 
6025
 
 
6026
  /* Copy the data if necessary. */
 
6027
  thd->count_cuted_fields= CHECK_FIELD_WARN;    // calc cuted fields
 
6028
  thd->cuted_fields=0L;
 
6029
  thd_proc_info(thd, "copy to tmp table");
 
6030
  copied=deleted=0;
 
6031
  /*
 
6032
    We do not copy data for MERGE tables. Only the children have data.
 
6033
    MERGE tables have HA_NO_COPY_ON_ALTER set.
 
6034
  */
 
6035
  if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
 
6036
  {
 
6037
    /* We don't want update TIMESTAMP fields during ALTER TABLE. */
 
6038
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
6039
    new_table->next_number_field=new_table->found_next_number_field;
 
6040
    error= copy_data_between_tables(table, new_table,
 
6041
                                    alter_info->create_list, ignore,
 
6042
                                   order_num, order, &copied, &deleted,
 
6043
                                    alter_info->keys_onoff,
 
6044
                                    alter_info->error_if_not_empty);
 
6045
  }
 
6046
  else
 
6047
  {
 
6048
    VOID(pthread_mutex_lock(&LOCK_open));
 
6049
    wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
6050
    VOID(pthread_mutex_unlock(&LOCK_open));
 
6051
    alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
6052
                            alter_info->keys_onoff);
 
6053
    error= ha_autocommit_or_rollback(thd, 0);
 
6054
    if (end_active_trans(thd))
 
6055
      error= 1;
 
6056
  }
 
6057
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
6058
 
 
6059
  if (table->s->tmp_table != NO_TMP_TABLE)
 
6060
  {
 
6061
    /* We changed a temporary table */
 
6062
    if (error)
 
6063
      goto err1;
 
6064
    /* Close lock if this is a transactional table */
 
6065
    if (thd->lock)
 
6066
    {
 
6067
      mysql_unlock_tables(thd, thd->lock);
 
6068
      thd->lock=0;
 
6069
    }
 
6070
    /* Remove link to old table and rename the new one */
 
6071
    close_temporary_table(thd, table, 1, 1);
 
6072
    /* Should pass the 'new_name' as we store table name in the cache */
 
6073
    if (rename_temporary_table(thd, new_table, new_db, new_name))
 
6074
      goto err1;
 
6075
    /* We don't replicate alter table statement on temporary tables */
 
6076
    if (!thd->current_stmt_binlog_row_based)
 
6077
      write_bin_log(thd, true, thd->query, thd->query_length);
 
6078
    goto end_temporary;
 
6079
  }
 
6080
 
 
6081
  if (new_table)
 
6082
  {
 
6083
    /*
 
6084
      Close the intermediate table that will be the new table.
 
6085
      Note that MERGE tables do not have their children attached here.
 
6086
    */
 
6087
    intern_close_table(new_table);
 
6088
    my_free(new_table,MYF(0));
 
6089
  }
 
6090
  VOID(pthread_mutex_lock(&LOCK_open));
 
6091
  if (error)
 
6092
  {
 
6093
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
6094
    VOID(pthread_mutex_unlock(&LOCK_open));
 
6095
    goto err;
 
6096
  }
 
6097
 
 
6098
  /*
 
6099
    Data is copied. Now we:
 
6100
    1) Wait until all other threads close old version of table.
 
6101
    2) Close instances of table open by this thread and replace them
 
6102
       with exclusive name-locks.
 
6103
    3) Rename the old table to a temp name, rename the new one to the
 
6104
       old name.
 
6105
    4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
 
6106
       we reopen new version of table.
 
6107
    5) Write statement to the binary log.
 
6108
    6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
 
6109
       remove name-locks from list of open tables and table cache.
 
6110
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
6111
       call to remove name-locks from table cache and list of open table.
 
6112
  */
 
6113
 
 
6114
  thd_proc_info(thd, "rename result table");
 
6115
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
 
6116
           current_pid, thd->thread_id);
 
6117
  if (lower_case_table_names)
 
6118
    my_casedn_str(files_charset_info, old_name);
 
6119
 
 
6120
  wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
6121
  close_data_files_and_morph_locks(thd, db, table_name);
 
6122
 
 
6123
  error=0;
 
6124
  save_old_db_type= old_db_type;
 
6125
 
 
6126
  /*
 
6127
    This leads to the storage engine (SE) not being notified for renames in
 
6128
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
6129
    more. If we have an intermediate table, then we notify the SE that
 
6130
    it should become the actual table. Later, we will recycle the old table.
 
6131
    However, in case of ALTER TABLE RENAME there might be no intermediate
 
6132
    table. This is when the old and new tables are compatible, according to
 
6133
    compare_table(). Then, we need one additional call to
 
6134
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
6135
    actual rename in the SE and the FRM is not touched. Note that, if the
 
6136
    table is renamed and the SE is also changed, then an intermediate table
 
6137
    is created and the additional call will not take place.
 
6138
  */
 
6139
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
 
6140
                         FN_TO_IS_TMP))
 
6141
  {
 
6142
    error=1;
 
6143
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
6144
  }
 
6145
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
 
6146
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
 
6147
  {
 
6148
    /* Try to get everything back. */
 
6149
    error=1;
 
6150
    VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
 
6151
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
6152
    VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
 
6153
                            FN_FROM_IS_TMP));
 
6154
  }
 
6155
 
 
6156
  if (error)
 
6157
  {
 
6158
    /* This shouldn't happen. But let us play it safe. */
 
6159
    goto err_with_placeholders;
 
6160
  }
 
6161
 
 
6162
  VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
 
6163
 
 
6164
end_online:
 
6165
  if (thd->locked_tables && new_name == table_name && new_db == db)
 
6166
  {
 
6167
    thd->in_lock_tables= 1;
 
6168
    error= reopen_tables(thd, 1, 1);
 
6169
    thd->in_lock_tables= 0;
 
6170
    if (error)
 
6171
      goto err_with_placeholders;
 
6172
  }
 
6173
  VOID(pthread_mutex_unlock(&LOCK_open));
 
6174
 
 
6175
  thd_proc_info(thd, "end");
 
6176
 
 
6177
  DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
 
6178
 
 
6179
  ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
 
6180
                      thd->query, thd->query_length,
 
6181
                      db, table_name);
 
6182
 
 
6183
  DBUG_ASSERT(!(mysql_bin_log.is_open() &&
 
6184
                thd->current_stmt_binlog_row_based &&
 
6185
                (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
 
6186
  write_bin_log(thd, true, thd->query, thd->query_length);
 
6187
 
 
6188
  if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
 
6189
  {
 
6190
    /*
 
6191
      For the alter table to be properly flushed to the logs, we
 
6192
      have to open the new table.  If not, we get a problem on server
 
6193
      shutdown. But we do not need to attach MERGE children.
 
6194
    */
 
6195
    char path[FN_REFLEN];
 
6196
    TABLE *t_table;
 
6197
    build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
 
6198
    t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
 
6199
    if (t_table)
 
6200
    {
 
6201
      intern_close_table(t_table);
 
6202
      my_free(t_table, MYF(0));
 
6203
    }
 
6204
    else
 
6205
      sql_print_warning("Could not open table %s.%s after rename\n",
 
6206
                        new_db,table_name);
 
6207
    ha_flush_logs(old_db_type);
 
6208
  }
 
6209
  table_list->table=0;                          // For query cache
 
6210
 
 
6211
  if (thd->locked_tables && (new_name != table_name || new_db != db))
 
6212
  {
 
6213
    /*
 
6214
      If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
 
6215
      to remove placeholders for the old table and for the target table
 
6216
      from the list of open tables and table cache. If we are not under
 
6217
      LOCK TABLES we can rely on close_thread_tables() doing this job.
 
6218
    */
 
6219
    pthread_mutex_lock(&LOCK_open);
 
6220
    unlink_open_table(thd, table, false);
 
6221
    unlink_open_table(thd, name_lock, false);
 
6222
    pthread_mutex_unlock(&LOCK_open);
 
6223
  }
 
6224
 
 
6225
end_temporary:
 
6226
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
6227
           (ulong) (copied + deleted), (ulong) deleted,
 
6228
           (ulong) thd->cuted_fields);
 
6229
  my_ok(thd, copied + deleted, 0L, tmp_name);
 
6230
  thd->some_tables_deleted=0;
 
6231
  DBUG_RETURN(false);
 
6232
 
 
6233
err1:
 
6234
  if (new_table)
 
6235
  {
 
6236
    /* close_temporary_table() frees the new_table pointer. */
 
6237
    close_temporary_table(thd, new_table, 1, 1);
 
6238
  }
 
6239
  else
 
6240
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
6241
 
 
6242
err:
 
6243
  /*
 
6244
    No default value was provided for a DATE/DATETIME field, the
 
6245
    current sql_mode doesn't allow the '0000-00-00' value and
 
6246
    the table to be altered isn't empty.
 
6247
    Report error here.
 
6248
  */
 
6249
  if (alter_info->error_if_not_empty && thd->row_count)
 
6250
  {
 
6251
    const char *f_val= 0;
 
6252
    enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
 
6253
    switch (alter_info->datetime_field->sql_type)
 
6254
    {
 
6255
      case MYSQL_TYPE_NEWDATE:
 
6256
        f_val= "0000-00-00";
 
6257
        t_type= MYSQL_TIMESTAMP_DATE;
 
6258
        break;
 
6259
      case MYSQL_TYPE_DATETIME:
 
6260
        f_val= "0000-00-00 00:00:00";
 
6261
        t_type= MYSQL_TIMESTAMP_DATETIME;
 
6262
        break;
 
6263
      default:
 
6264
        /* Shouldn't get here. */
 
6265
        DBUG_ASSERT(0);
 
6266
    }
 
6267
    bool save_abort_on_warning= thd->abort_on_warning;
 
6268
    thd->abort_on_warning= true;
 
6269
    make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
 
6270
                                 f_val, strlength(f_val), t_type,
 
6271
                                 alter_info->datetime_field->field_name);
 
6272
    thd->abort_on_warning= save_abort_on_warning;
 
6273
  }
 
6274
  if (name_lock)
 
6275
  {
 
6276
    pthread_mutex_lock(&LOCK_open);
 
6277
    unlink_open_table(thd, name_lock, false);
 
6278
    pthread_mutex_unlock(&LOCK_open);
 
6279
  }
 
6280
  DBUG_RETURN(true);
 
6281
 
 
6282
err_with_placeholders:
 
6283
  /*
 
6284
    An error happened while we were holding exclusive name-lock on table
 
6285
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
6286
    from list of open tables list and table cache.
 
6287
  */
 
6288
  unlink_open_table(thd, table, false);
 
6289
  if (name_lock)
 
6290
    unlink_open_table(thd, name_lock, false);
 
6291
  VOID(pthread_mutex_unlock(&LOCK_open));
 
6292
  DBUG_RETURN(true);
 
6293
}
 
6294
/* mysql_alter_table */
 
6295
 
 
6296
static int
 
6297
copy_data_between_tables(TABLE *from,TABLE *to,
 
6298
                         List<Create_field> &create,
 
6299
                         bool ignore,
 
6300
                         uint order_num, ORDER *order,
 
6301
                         ha_rows *copied,
 
6302
                         ha_rows *deleted,
 
6303
                         enum enum_enable_or_disable keys_onoff,
 
6304
                         bool error_if_not_empty)
 
6305
{
 
6306
  int error;
 
6307
  Copy_field *copy,*copy_end;
 
6308
  ulong found_count,delete_count;
 
6309
  THD *thd= current_thd;
 
6310
  uint length= 0;
 
6311
  SORT_FIELD *sortorder;
 
6312
  READ_RECORD info;
 
6313
  TABLE_LIST   tables;
 
6314
  List<Item>   fields;
 
6315
  List<Item>   all_fields;
 
6316
  ha_rows examined_rows;
 
6317
  bool auto_increment_field_copied= 0;
 
6318
  ulong save_sql_mode;
 
6319
  ulonglong prev_insert_id;
 
6320
  DBUG_ENTER("copy_data_between_tables");
 
6321
 
 
6322
  /*
 
6323
    Turn off recovery logging since rollback of an alter table is to
 
6324
    delete the new table so there is no need to log the changes to it.
 
6325
    
 
6326
    This needs to be done before external_lock
 
6327
  */
 
6328
  error= ha_enable_transaction(thd, false);
 
6329
  if (error)
 
6330
    DBUG_RETURN(-1);
 
6331
  
 
6332
  if (!(copy= new Copy_field[to->s->fields]))
 
6333
    DBUG_RETURN(-1);                            /* purecov: inspected */
 
6334
 
 
6335
  if (to->file->ha_external_lock(thd, F_WRLCK))
 
6336
    DBUG_RETURN(-1);
 
6337
 
 
6338
  /* We need external lock before we can disable/enable keys */
 
6339
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
6340
 
 
6341
  /* We can abort alter table for any table type */
 
6342
  thd->abort_on_warning= !ignore;
 
6343
 
 
6344
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
6345
  to->file->ha_start_bulk_insert(from->file->stats.records);
 
6346
 
 
6347
  save_sql_mode= thd->variables.sql_mode;
 
6348
 
 
6349
  List_iterator<Create_field> it(create);
 
6350
  Create_field *def;
 
6351
  copy_end=copy;
 
6352
  for (Field **ptr=to->field ; *ptr ; ptr++)
 
6353
  {
 
6354
    def=it++;
 
6355
    if (def->field)
 
6356
    {
 
6357
      if (*ptr == to->next_number_field)
 
6358
      {
 
6359
        auto_increment_field_copied= true;
 
6360
        /*
 
6361
          If we are going to copy contents of one auto_increment column to
 
6362
          another auto_increment column it is sensible to preserve zeroes.
 
6363
          This condition also covers case when we are don't actually alter
 
6364
          auto_increment column.
 
6365
        */
 
6366
        if (def->field == from->found_next_number_field)
 
6367
          thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
 
6368
      }
 
6369
      (copy_end++)->set(*ptr,def->field,0);
 
6370
    }
 
6371
 
 
6372
  }
 
6373
 
 
6374
  found_count=delete_count=0;
 
6375
 
 
6376
  if (order)
 
6377
  {
 
6378
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
 
6379
    {
 
6380
      char warn_buff[MYSQL_ERRMSG_SIZE];
 
6381
      snprintf(warn_buff, sizeof(warn_buff), 
 
6382
               "ORDER BY ignored as there is a user-defined clustered index"
 
6383
               " in the table '%-.192s'", from->s->table_name.str);
 
6384
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
6385
                   warn_buff);
 
6386
    }
 
6387
    else
 
6388
    {
 
6389
      from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
 
6390
                                                MYF(MY_FAE | MY_ZEROFILL));
 
6391
      bzero((char *) &tables, sizeof(tables));
 
6392
      tables.table= from;
 
6393
      tables.alias= tables.table_name= from->s->table_name.str;
 
6394
      tables.db= from->s->db.str;
 
6395
      error= 1;
 
6396
 
 
6397
      if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
 
6398
          setup_order(thd, thd->lex->select_lex.ref_pointer_array,
 
6399
                      &tables, fields, all_fields, order) ||
 
6400
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
6401
          (from->sort.found_records= filesort(thd, from, sortorder, length,
 
6402
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
6403
                                              1, &examined_rows)) ==
 
6404
          HA_POS_ERROR)
 
6405
        goto err;
 
6406
    }
 
6407
  };
 
6408
 
 
6409
  /* Tell handler that we have values for all columns in the to table */
 
6410
  to->use_all_columns();
 
6411
  init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
 
6412
  if (ignore)
 
6413
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
6414
  thd->row_count= 0;
 
6415
  restore_record(to, s->default_values);        // Create empty record
 
6416
  while (!(error=info.read_record(&info)))
 
6417
  {
 
6418
    if (thd->killed)
 
6419
    {
 
6420
      thd->send_kill_message();
 
6421
      error= 1;
 
6422
      break;
 
6423
    }
 
6424
    thd->row_count++;
 
6425
    /* Return error if source table isn't empty. */
 
6426
    if (error_if_not_empty)
 
6427
    {
 
6428
      error= 1;
 
6429
      break;
 
6430
    }
 
6431
    if (to->next_number_field)
 
6432
    {
 
6433
      if (auto_increment_field_copied)
 
6434
        to->auto_increment_field_not_null= true;
 
6435
      else
 
6436
        to->next_number_field->reset();
 
6437
    }
 
6438
    
 
6439
    for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
6440
    {
 
6441
      copy_ptr->do_copy(copy_ptr);
 
6442
    }
 
6443
    prev_insert_id= to->file->next_insert_id;
 
6444
    error=to->file->ha_write_row(to->record[0]);
 
6445
    to->auto_increment_field_not_null= false;
 
6446
    if (error)
 
6447
    {
 
6448
      if (!ignore ||
 
6449
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
6450
      {
 
6451
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
6452
         {
 
6453
           uint key_nr= to->file->get_dup_key(error);
 
6454
           if ((int) key_nr >= 0)
 
6455
           {
 
6456
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
6457
             if (key_nr == 0 &&
 
6458
                 (to->key_info[0].key_part[0].field->flags &
 
6459
                  AUTO_INCREMENT_FLAG))
 
6460
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
6461
             to->file->print_keydup_error(key_nr, err_msg);
 
6462
             break;
 
6463
           }
 
6464
         }
 
6465
 
 
6466
        to->file->print_error(error,MYF(0));
 
6467
        break;
 
6468
      }
 
6469
      to->file->restore_auto_increment(prev_insert_id);
 
6470
      delete_count++;
 
6471
    }
 
6472
    else
 
6473
      found_count++;
 
6474
  }
 
6475
  end_read_record(&info);
 
6476
  free_io_cache(from);
 
6477
  delete [] copy;                               // This is never 0
 
6478
 
 
6479
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
6480
  {
 
6481
    to->file->print_error(my_errno,MYF(0));
 
6482
    error=1;
 
6483
  }
 
6484
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
6485
 
 
6486
  if (ha_enable_transaction(thd, true))
 
6487
  {
 
6488
    error= 1;
 
6489
    goto err;
 
6490
  }
 
6491
 
 
6492
  /*
 
6493
    Ensure that the new table is saved properly to disk so that we
 
6494
    can do a rename
 
6495
  */
 
6496
  if (ha_autocommit_or_rollback(thd, 0))
 
6497
    error=1;
 
6498
  if (end_active_trans(thd))
 
6499
    error=1;
 
6500
 
 
6501
 err:
 
6502
  thd->variables.sql_mode= save_sql_mode;
 
6503
  thd->abort_on_warning= 0;
 
6504
  free_io_cache(from);
 
6505
  *copied= found_count;
 
6506
  *deleted=delete_count;
 
6507
  to->file->ha_release_auto_increment();
 
6508
  if (to->file->ha_external_lock(thd,F_UNLCK))
 
6509
    error=1;
 
6510
  DBUG_RETURN(error > 0 ? -1 : 0);
 
6511
}
 
6512
 
 
6513
 
 
6514
/*
 
6515
  Recreates tables by calling mysql_alter_table().
 
6516
 
 
6517
  SYNOPSIS
 
6518
    mysql_recreate_table()
 
6519
    thd                 Thread handler
 
6520
    tables              Tables to recreate
 
6521
 
 
6522
 RETURN
 
6523
    Like mysql_alter_table().
 
6524
*/
 
6525
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
 
6526
{
 
6527
  HA_CREATE_INFO create_info;
 
6528
  Alter_info alter_info;
 
6529
 
 
6530
  DBUG_ENTER("mysql_recreate_table");
 
6531
  DBUG_ASSERT(!table_list->next_global);
 
6532
  /*
 
6533
    table_list->table has been closed and freed. Do not reference
 
6534
    uninitialized data. open_tables() could fail.
 
6535
  */
 
6536
  table_list->table= NULL;
 
6537
 
 
6538
  bzero((char*) &create_info, sizeof(create_info));
 
6539
  create_info.row_type=ROW_TYPE_NOT_USED;
 
6540
  create_info.default_table_charset=default_charset_info;
 
6541
  /* Force alter table to recreate table */
 
6542
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
6543
  DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
 
6544
                                table_list, &alter_info, 0,
 
6545
                                (ORDER *) 0, 0));
 
6546
}
 
6547
 
 
6548
 
 
6549
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
 
6550
                          HA_CHECK_OPT *check_opt)
 
6551
{
 
6552
  TABLE_LIST *table;
 
6553
  List<Item> field_list;
 
6554
  Item *item;
 
6555
  Protocol *protocol= thd->protocol;
 
6556
  DBUG_ENTER("mysql_checksum_table");
 
6557
 
 
6558
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
6559
  item->maybe_null= 1;
 
6560
  field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
 
6561
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
6562
  item->maybe_null= 1;
 
6563
  if (protocol->send_fields(&field_list,
 
6564
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
6565
    DBUG_RETURN(true);
 
6566
 
 
6567
  /* Open one table after the other to keep lock time as short as possible. */
 
6568
  for (table= tables; table; table= table->next_local)
 
6569
  {
 
6570
    char table_name[NAME_LEN*2+2];
 
6571
    TABLE *t;
 
6572
 
 
6573
    strxmov(table_name, table->db ,".", table->table_name, NullS);
 
6574
 
 
6575
    t= table->table= open_n_lock_single_table(thd, table, TL_READ);
 
6576
    thd->clear_error();                 // these errors shouldn't get client
 
6577
 
 
6578
    protocol->prepare_for_resend();
 
6579
    protocol->store(table_name, system_charset_info);
 
6580
 
 
6581
    if (!t)
 
6582
    {
 
6583
      /* Table didn't exist */
 
6584
      protocol->store_null();
 
6585
      thd->clear_error();
 
6586
    }
 
6587
    else
 
6588
    {
 
6589
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
6590
          !(check_opt->flags & T_EXTEND))
 
6591
        protocol->store((ulonglong)t->file->checksum());
 
6592
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
6593
               (check_opt->flags & T_QUICK))
 
6594
        protocol->store_null();
 
6595
      else
 
6596
      {
 
6597
        /* calculating table's checksum */
 
6598
        ha_checksum crc= 0;
 
6599
        uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
6600
 
 
6601
        t->use_all_columns();
 
6602
 
 
6603
        if (t->file->ha_rnd_init(1))
 
6604
          protocol->store_null();
 
6605
        else
 
6606
        {
 
6607
          for (;;)
 
6608
          {
 
6609
            ha_checksum row_crc= 0;
 
6610
            int error= t->file->rnd_next(t->record[0]);
 
6611
            if (unlikely(error))
 
6612
            {
 
6613
              if (error == HA_ERR_RECORD_DELETED)
 
6614
                continue;
 
6615
              break;
 
6616
            }
 
6617
            if (t->s->null_bytes)
 
6618
            {
 
6619
              /* fix undefined null bits */
 
6620
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
6621
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
6622
                t->record[0][0] |= 1;
 
6623
 
 
6624
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
6625
            }
 
6626
 
 
6627
            for (uint i= 0; i < t->s->fields; i++ )
 
6628
            {
 
6629
              Field *f= t->field[i];
 
6630
              if ((f->type() == MYSQL_TYPE_BLOB) ||
 
6631
                  (f->type() == MYSQL_TYPE_VARCHAR))
 
6632
              {
 
6633
                String tmp;
 
6634
                f->val_str(&tmp);
 
6635
                row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
 
6636
              }
 
6637
              else
 
6638
                row_crc= my_checksum(row_crc, f->ptr,
 
6639
                                     f->pack_length());
 
6640
            }
 
6641
 
 
6642
            crc+= row_crc;
 
6643
          }
 
6644
          protocol->store((ulonglong)crc);
 
6645
          t->file->ha_rnd_end();
 
6646
        }
 
6647
      }
 
6648
      thd->clear_error();
 
6649
      close_thread_tables(thd);
 
6650
      table->table=0;                           // For query cache
 
6651
    }
 
6652
    if (protocol->write())
 
6653
      goto err;
 
6654
  }
 
6655
 
 
6656
  my_eof(thd);
 
6657
  DBUG_RETURN(false);
 
6658
 
 
6659
 err:
 
6660
  close_thread_tables(thd);                     // Shouldn't be needed
 
6661
  if (table)
 
6662
    table->table=0;
 
6663
  DBUG_RETURN(true);
 
6664
}
 
6665
 
 
6666
static bool check_engine(THD *thd, const char *table_name,
 
6667
                         HA_CREATE_INFO *create_info)
 
6668
{
 
6669
  handlerton **new_engine= &create_info->db_type;
 
6670
  handlerton *req_engine= *new_engine;
 
6671
  bool no_substitution= 1;
 
6672
  if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
 
6673
                                  no_substitution, 1)))
 
6674
    return true;
 
6675
 
 
6676
  if (req_engine && req_engine != *new_engine)
 
6677
  {
 
6678
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
6679
                       ER_WARN_USING_OTHER_HANDLER,
 
6680
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
6681
                       ha_resolve_storage_engine_name(*new_engine),
 
6682
                       table_name);
 
6683
  }
 
6684
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
6685
      ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
 
6686
  {
 
6687
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
6688
    {
 
6689
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
6690
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
 
6691
      *new_engine= 0;
 
6692
      return true;
 
6693
    }
 
6694
    *new_engine= myisam_hton;
 
6695
  }
 
6696
  return false;
 
6697
}