~drizzle-trunk/drizzle/development

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