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