~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_table.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

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