~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)
473
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
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 */
1475
	      char warn_buff[MYSQL_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);
1 by brian
clean slate
1478
	      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
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 */
1514
	  char warn_buff[MYSQL_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);
1 by brian
clean slate
1517
	  push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
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
1859
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
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)
1945
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
1946
                   "DATA DIRECTORY option ignored");
1947
    if (create_info->index_file_name)
1948
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
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;
1 by brian
clean slate
1994
  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
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
      {
2043
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
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)
2541
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
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 */
2549
      char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
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
    {
2631
      List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
2632
      MYSQL_ERROR *err;
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
      }
2645
      mysql_reset_errors(thd, true);
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.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
2953
  memset((char*) &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
  {
3171
    char warn_buff[MYSQL_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);
1 by brian
clean slate
3174
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
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
  {
3722
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
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;
4074
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
4075
    create_info->default_table_charset= table->s->table_charset;
4076
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
4077
    {
4078
    /* Table has an autoincrement, copy value to new table */
4079
    table->file->info(HA_STATUS_AUTO);
4080
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
4081
  }
4082
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4083
    create_info->key_block_size= table->s->key_block_size;
4084
  if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
4085
    create_info->transactional= table->s->transactional;
4086
4087
  restore_record(table, s->default_values);     // Empty record for DEFAULT
4088
  Create_field *def;
4089
4090
    /*
4091
    First collect all fields from table which isn't in drop_list
4092
    */
4093
  Field **f_ptr,*field;
4094
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
4095
    {
4096
    /* Check if field should be dropped */
4097
    Alter_drop *drop;
4098
    drop_it.rewind();
4099
    while ((drop=drop_it++))
4100
    {
4101
      if (drop->type == Alter_drop::COLUMN &&
4102
	  !my_strcasecmp(system_charset_info,field->field_name, drop->name))
4103
    {
4104
	/* Reset auto_increment value if it was dropped */
4105
	if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
4106
	    !(used_fields & HA_CREATE_USED_AUTO))
4107
      {
4108
	  create_info->auto_increment_value=0;
4109
	  create_info->used_fields|=HA_CREATE_USED_AUTO;
4110
      }
4111
	break;
4112
    }
4113
  }
4114
    if (drop)
4115
      {
4116
      drop_it.remove();
4117
      continue;
4118
    }
4119
    /* Check if field is changed */
4120
    def_it.rewind();
4121
    while ((def=def_it++))
4122
    {
4123
      if (def->change &&
4124
	  !my_strcasecmp(system_charset_info,field->field_name, def->change))
4125
	break;
4126
    }
4127
    if (def)
4128
    {						// Field is changed
4129
      def->field=field;
4130
      if (!def->after)
4131
	{
4132
	new_create_list.push_back(def);
4133
	def_it.remove();
4134
	}
4135
      }
4136
      else
4137
      {
4138
      /*
4139
        This field was not dropped and not changed, add it to the list
4140
        for the new table.
4141
      */
4142
      def= new Create_field(field, field);
4143
      new_create_list.push_back(def);
4144
      alter_it.rewind();			// Change default if ALTER
4145
      Alter_column *alter;
4146
      while ((alter=alter_it++))
4147
        {
4148
	if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
4149
	  break;
4150
        }
4151
      if (alter)
4152
	{
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
4153
	if (def->sql_type == DRIZZLE_TYPE_BLOB)
1 by brian
clean slate
4154
	{
4155
	  my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
4156
          goto err;
4157
	}
4158
	if ((def->def=alter->def))              // Use new default
4159
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
4160
        else
4161
          def->flags|= NO_DEFAULT_VALUE_FLAG;
4162
	alter_it.remove();
4163
      }
4164
    }
4165
  }
4166
  def_it.rewind();
4167
  while ((def=def_it++))			// Add new columns
4168
  {
4169
    if (def->change && ! def->field)
4170
    {
4171
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
4172
      goto err;
4173
    }
4174
      /*
4175
      Check that the DATE/DATETIME not null field we are going to add is
4176
      either has a default value or the '0000-00-00' is allowed by the
4177
      set sql mode.
4178
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
4179
      flag to allow ALTER TABLE only if the table to be altered is empty.
4180
      */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
4181
    if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
4182
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
1 by brian
clean slate
4183
         !alter_info->datetime_field &&
4184
         !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
4185
         thd->variables.sql_mode & MODE_NO_ZERO_DATE)
4186
    {
4187
        alter_info->datetime_field= def;
55 by brian
Update for using real bool types.
4188
        alter_info->error_if_not_empty= true;
1 by brian
clean slate
4189
    }
4190
    if (!def->after)
4191
      new_create_list.push_back(def);
4192
    else if (def->after == first_keyword)
4193
      new_create_list.push_front(def);
4194
    else
4195
    {
4196
      Create_field *find;
4197
      find_it.rewind();
4198
      while ((find=find_it++))			// Add new columns
4199
      {
4200
	if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
4201
	  break;
4202
  }
4203
      if (!find)
4204
  {
4205
	my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
4206
    goto err;
4207
  }
4208
      find_it.after(def);			// Put element after this
4209
      /*
4210
        XXX: hack for Bug#28427.
4211
        If column order has changed, force OFFLINE ALTER TABLE
4212
        without querying engine capabilities.  If we ever have an
4213
        engine that supports online ALTER TABLE CHANGE COLUMN
4214
        <name> AFTER <name1> (Falcon?), this fix will effectively
4215
        disable the capability.
4216
        TODO: detect the situation in compare_tables, behave based
4217
        on engine capabilities.
4218
      */
4219
      if (alter_info->build_method == HA_BUILD_ONLINE)
4220
      {
4221
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4222
        goto err;
4223
      }
4224
      alter_info->build_method= HA_BUILD_OFFLINE;
4225
    }
4226
  }
4227
  if (alter_info->alter_list.elements)
4228
  {
4229
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
4230
             alter_info->alter_list.head()->name, table->s->table_name.str);
4231
    goto err;
4232
    }
4233
  if (!new_create_list.elements)
4234
    {
4235
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
4236
               MYF(0));
4237
    goto err;
4238
    }
4239
4240
    /*
4241
    Collect all keys which isn't in drop list. Add only those
4242
    for which some fields exists.
4243
    */
4244
4245
  for (uint i=0 ; i < table->s->keys ; i++,key_info++)
4246
    {
4247
    char *key_name= key_info->name;
4248
    Alter_drop *drop;
4249
    drop_it.rewind();
4250
    while ((drop=drop_it++))
4251
      {
4252
      if (drop->type == Alter_drop::KEY &&
4253
	  !my_strcasecmp(system_charset_info,key_name, drop->name))
4254
	break;
4255
      }
4256
    if (drop)
4257
        {
4258
      drop_it.remove();
4259
      continue;
4260
    }
4261
4262
    KEY_PART_INFO *key_part= key_info->key_part;
4263
    key_parts.empty();
4264
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
4265
    {
4266
      if (!key_part->field)
4267
	continue;				// Wrong field (from UNIREG)
4268
      const char *key_part_name=key_part->field->field_name;
4269
      Create_field *cfield;
4270
      field_it.rewind();
4271
      while ((cfield=field_it++))
4272
    {
4273
	if (cfield->change)
4274
    {
4275
	  if (!my_strcasecmp(system_charset_info, key_part_name,
4276
			     cfield->change))
4277
	    break;
4278
	}
4279
	else if (!my_strcasecmp(system_charset_info,
4280
				key_part_name, cfield->field_name))
4281
	  break;
4282
      }
4283
      if (!cfield)
4284
	continue;				// Field is removed
4285
      uint key_part_length=key_part->length;
4286
      if (cfield->field)			// Not new field
4287
      {
4288
        /*
4289
          If the field can't have only a part used in a key according to its
4290
          new type, or should not be used partially according to its
4291
          previous type, or the field length is less than the key part
4292
          length, unset the key part length.
4293
4294
          We also unset the key part length if it is the same as the
4295
          old field's length, so the whole new field will be used.
4296
4297
          BLOBs may have cfield->length == 0, which is why we test it before
4298
          checking whether cfield->length < key_part_length (in chars).
4299
         */
4300
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
4301
            !Field::type_can_have_key_part(cfield->sql_type) ||
4302
            (cfield->field->field_length == key_part_length &&
4303
             !f_is_blob(key_part->key_type)) ||
4304
	    (cfield->length && (cfield->length < key_part_length /
4305
                                key_part->field->charset()->mbmaxlen)))
4306
	  key_part_length= 0;			// Use whole field
4307
      }
4308
      key_part_length /= key_part->field->charset()->mbmaxlen;
4309
      key_parts.push_back(new Key_part_spec(cfield->field_name,
4310
                                            strlen(cfield->field_name),
4311
					    key_part_length));
4312
    }
4313
    if (key_parts.elements)
4314
    {
4315
      KEY_CREATE_INFO key_create_info;
4316
      Key *key;
4317
      enum Key::Keytype key_type;
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
4318
      memset((char*) &key_create_info, 0, sizeof(key_create_info));
1 by brian
clean slate
4319
4320
      key_create_info.algorithm= key_info->algorithm;
4321
      if (key_info->flags & HA_USES_BLOCK_SIZE)
4322
        key_create_info.block_size= key_info->block_size;
4323
      if (key_info->flags & HA_USES_COMMENT)
4324
        key_create_info.comment= key_info->comment;
4325
4326
      if (key_info->flags & HA_NOSAME)
4327
      {
4328
        if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
4329
          key_type= Key::PRIMARY;
4330
        else
4331
          key_type= Key::UNIQUE;
4332
      }
4333
      else
4334
        key_type= Key::MULTIPLE;
4335
4336
      key= new Key(key_type, key_name, strlen(key_name),
4337
                   &key_create_info,
4338
                   test(key_info->flags & HA_GENERATED_KEY),
4339
                   key_parts);
4340
      new_key_list.push_back(key);
4341
    }
4342
  }
4343
  {
4344
    Key *key;
4345
    while ((key=key_it++))			// Add new keys
4346
    {
4347
      if (key->type != Key::FOREIGN_KEY)
4348
        new_key_list.push_back(key);
4349
      if (key->name.str &&
4350
	  !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
4351
      {
4352
	my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
4353
        goto err;
4354
      }
4355
    }
4356
  }
4357
4358
  if (alter_info->drop_list.elements)
4359
  {
4360
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4361
             alter_info->drop_list.head()->name);
4362
    goto err;
4363
  }
4364
  if (alter_info->alter_list.elements)
4365
  {
4366
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4367
             alter_info->alter_list.head()->name);
4368
    goto err;
4369
  }
4370
4371
  if (!create_info->comment.str)
4372
  {
4373
    create_info->comment.str= table->s->comment.str;
4374
    create_info->comment.length= table->s->comment.length;
4375
  }
4376
4377
  table->file->update_create_info(create_info);
4378
  if ((create_info->table_options &
4379
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
4380
      (used_fields & HA_CREATE_USED_PACK_KEYS))
4381
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
4382
  if (create_info->table_options &
4383
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
4384
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
4385
  if (create_info->table_options &
4386
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
4387
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
4388
			  HA_OPTION_NO_DELAY_KEY_WRITE);
4389
  create_info->table_options|= db_create_options;
4390
4391
  if (table->s->tmp_table)
4392
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
4393
55 by brian
Update for using real bool types.
4394
  rc= false;
1 by brian
clean slate
4395
  alter_info->create_list.swap(new_create_list);
4396
  alter_info->key_list.swap(new_key_list);
4397
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
4398
  return(rc);
1 by brian
clean slate
4399
}
4400
4401
4402
/*
4403
  Alter table
4404
4405
  SYNOPSIS
4406
    mysql_alter_table()
4407
      thd              Thread handle
4408
      new_db           If there is a RENAME clause
4409
      new_name         If there is a RENAME clause
4410
      create_info      Information from the parsing phase about new
4411
                       table properties.
4412
      table_list       The table to change.
4413
      alter_info       Lists of fields, keys to be changed, added
4414
                       or dropped.
4415
      order_num        How many ORDER BY fields has been specified.
4416
      order            List of fields to ORDER BY.
4417
      ignore           Whether we have ALTER IGNORE TABLE
4418
4419
  DESCRIPTION
4420
    This is a veery long function and is everything but the kitchen sink :)
4421
    It is used to alter a table and not only by ALTER TABLE but also
4422
    CREATE|DROP INDEX are mapped on this function.
4423
4424
    When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
4425
    or both, then this function short cuts its operation by renaming
4426
    the table and/or enabling/disabling the keys. In this case, the FRM is
4427
    not changed, directly by mysql_alter_table. However, if there is a
4428
    RENAME + change of a field, or an index, the short cut is not used.
4429
    See how `create_list` is used to generate the new FRM regarding the
4430
    structure of the fields. The same is done for the indices of the table.
4431
4432
    Important is the fact, that this function tries to do as little work as
4433
    possible, by finding out whether a intermediate table is needed to copy
4434
    data into and when finishing the altering to use it as the original table.
4435
    For this reason the function compare_tables() is called, which decides
4436
    based on all kind of data how similar are the new and the original
4437
    tables.
4438
4439
  RETURN VALUES
55 by brian
Update for using real bool types.
4440
    false  OK
4441
    true   Error
1 by brian
clean slate
4442
*/
4443
4444
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4445
                       HA_CREATE_INFO *create_info,
4446
                       TABLE_LIST *table_list,
4447
                       Alter_info *alter_info,
4448
                       uint order_num, ORDER *order, bool ignore)
4449
{
4450
  TABLE *table, *new_table=0, *name_lock= 0;;
4451
  int error= 0;
4452
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4453
  char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4454
  char path[FN_REFLEN];
4455
  ha_rows copied= 0,deleted= 0;
4456
  handlerton *old_db_type, *new_db_type, *save_old_db_type;
4457
  legacy_db_type table_type;
4458
  frm_type_enum frm_type;
4459
4460
  if (table_list && table_list->schema_table)
4461
  {
4462
    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
4463
    return(true);
1 by brian
clean slate
4464
  }
4465
4466
  /*
4467
    Assign variables table_name, new_name, db, new_db, path
4468
    to simplify further comparisons: we want to see if it's a RENAME
4469
    later just by comparing the pointers, avoiding the need for strcmp.
4470
  */
4471
  thd_proc_info(thd, "init");
4472
  table_name=table_list->table_name;
4473
  alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
4474
  db=table_list->db;
4475
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
4476
    new_db= db;
4477
  build_table_filename(path, sizeof(path), db, table_name, "", 0);
4478
55 by brian
Update for using real bool types.
4479
  mysql_ha_rm_tables(thd, table_list, false);
1 by brian
clean slate
4480
4481
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
4482
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4483
    /* 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
4484
    return(mysql_discard_or_import_tablespace(thd,table_list,
108 by Brian Aker
Removed unwanted ALTER TABLESPACE, left in valuable bits.
4485
                                              alter_info->tablespace_op));
1 by brian
clean slate
4486
  strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, 
4487
           "/", table_name, reg_ext, NullS);
4488
  (void) unpack_filename(new_name_buff, new_name_buff);
4489
  /*
4490
    If this is just a rename of a view, short cut to the
4491
    following scenario: 1) lock LOCK_open 2) do a RENAME
4492
    2) unlock LOCK_open.
4493
    This is a copy-paste added to make sure
4494
    ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
4495
    as an independent branch in mysql_execute_command. The need
4496
    for a copy-paste arose because the main code flow of ALTER TABLE
4497
    ... RENAME tries to use open_ltable, which does not work for views
4498
    (open_ltable was never modified to merge table lists of child tables
4499
    into the main table list, like open_tables does).
4500
    This code is wrong and will be removed, please do not copy.
4501
  */
4502
  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
4503
4504
  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
4505
    return(true);
1 by brian
clean slate
4506
  table->use_all_columns();
4507
4508
  /*
4509
    Prohibit changing of the UNION list of a non-temporary MERGE table
4510
    under LOCK tables. It would be quite difficult to reuse a shrinked
4511
    set of tables from the old table or to open a new TABLE object for
4512
    an extended list and verify that they belong to locked tables.
4513
  */
4514
  if (thd->locked_tables &&
4515
      (create_info->used_fields & HA_CREATE_USED_UNION) &&
4516
      (table->s->tmp_table == NO_TMP_TABLE))
4517
  {
4518
    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
4519
    return(true);
1 by brian
clean slate
4520
  }
4521
4522
  /* Check that we are not trying to rename to an existing table */
4523
  if (new_name)
4524
  {
4525
    strmov(new_name_buff,new_name);
4526
    strmov(new_alias= new_alias_buff, new_name);
4527
    if (lower_case_table_names)
4528
    {
4529
      if (lower_case_table_names != 2)
4530
      {
4531
	my_casedn_str(files_charset_info, new_name_buff);
4532
	new_alias= new_name;			// Create lower case table name
4533
      }
4534
      my_casedn_str(files_charset_info, new_name);
4535
    }
4536
    if (new_db == db &&
4537
	!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
4538
    {
4539
      /*
4540
	Source and destination table names are equal: make later check
4541
	easier.
4542
      */
4543
      new_alias= new_name= table_name;
4544
    }
4545
    else
4546
    {
4547
      if (table->s->tmp_table != NO_TMP_TABLE)
4548
      {
4549
	if (find_temporary_table(thd,new_db,new_name_buff))
4550
	{
4551
	  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
4552
	  return(true);
1 by brian
clean slate
4553
	}
4554
      }
4555
      else
4556
      {
4557
        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
4558
          return(true);
1 by brian
clean slate
4559
        if (!name_lock)
4560
        {
4561
	  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
4562
	  return(true);
1 by brian
clean slate
4563
        }
4564
4565
        build_table_filename(new_name_buff, sizeof(new_name_buff),
4566
                             new_db, new_name_buff, reg_ext, 0);
4567
        if (!access(new_name_buff, F_OK))
4568
	{
4569
	  /* Table will be closed in do_command() */
4570
	  my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4571
	  goto err;
4572
	}
4573
      }
4574
    }
4575
  }
4576
  else
4577
  {
4578
    new_alias= (lower_case_table_names == 2) ? alias : table_name;
4579
    new_name= table_name;
4580
  }
4581
4582
  old_db_type= table->s->db_type();
4583
  if (!create_info->db_type)
4584
  {
4585
    create_info->db_type= old_db_type;
4586
  }
4587
4588
  if (check_engine(thd, new_name, create_info))
4589
    goto err;
4590
  new_db_type= create_info->db_type;
4591
186 by Brian Aker
Partial fix for alter table
4592
  if (new_db_type != old_db_type &&
1 by brian
clean slate
4593
      !table->file->can_switch_engines())
4594
  {
186 by Brian Aker
Partial fix for alter table
4595
    assert(0);
1 by brian
clean slate
4596
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
4597
    goto err;
4598
  }
4599
4600
  if (create_info->row_type == ROW_TYPE_NOT_USED)
4601
    create_info->row_type= table->s->row_type;
4602
4603
  if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
4604
      ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
4605
  {
4606
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
4607
    goto err;
4608
  }
4609
4610
  thd_proc_info(thd, "setup");
4611
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
4612
      !table->s->tmp_table) // no need to touch frm
4613
  {
4614
    switch (alter_info->keys_onoff) {
4615
    case LEAVE_AS_IS:
4616
      break;
4617
    case ENABLE:
4618
      /*
4619
        wait_while_table_is_used() ensures that table being altered is
4620
        opened only by this thread and that TABLE::TABLE_SHARE::version
4621
        of TABLE object corresponding to this table is 0.
4622
        The latter guarantees that no DML statement will open this table
4623
        until ALTER TABLE finishes (i.e. until close_thread_tables())
4624
        while the fact that the table is still open gives us protection
4625
        from concurrent DDL statements.
4626
      */
4627
      VOID(pthread_mutex_lock(&LOCK_open));
4628
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4629
      VOID(pthread_mutex_unlock(&LOCK_open));
4630
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4631
      /* COND_refresh will be signaled in close_thread_tables() */
4632
      break;
4633
    case DISABLE:
4634
      VOID(pthread_mutex_lock(&LOCK_open));
4635
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4636
      VOID(pthread_mutex_unlock(&LOCK_open));
4637
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4638
      /* COND_refresh will be signaled in close_thread_tables() */
4639
      break;
4640
    default:
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
4641
      assert(false);
1 by brian
clean slate
4642
      error= 0;
4643
      break;
4644
    }
4645
    if (error == HA_ERR_WRONG_COMMAND)
4646
    {
4647
      error= 0;
4648
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4649
			  ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4650
			  table->alias);
4651
    }
4652
4653
    VOID(pthread_mutex_lock(&LOCK_open));
4654
    /*
4655
      Unlike to the above case close_cached_table() below will remove ALL
4656
      instances of TABLE from table cache (it will also remove table lock
4657
      held by this thread). So to make actual table renaming and writing
4658
      to binlog atomic we have to put them into the same critical section
4659
      protected by LOCK_open mutex. This also removes gap for races between
4660
      access() and mysql_rename_table() calls.
4661
    */
4662
4663
    if (!error && (new_name != table_name || new_db != db))
4664
    {
4665
      thd_proc_info(thd, "rename");
4666
      /*
4667
        Then do a 'simple' rename of the table. First we need to close all
4668
        instances of 'source' table.
4669
      */
4670
      close_cached_table(thd, table);
4671
      /*
4672
        Then, we want check once again that target table does not exist.
4673
        Actually the order of these two steps does not matter since
4674
        earlier we took name-lock on the target table, so we do them
4675
        in this particular order only to be consistent with 5.0, in which
4676
        we don't take this name-lock and where this order really matters.
4677
        TODO: Investigate if we need this access() check at all.
4678
      */
4679
      if (!access(new_name_buff,F_OK))
4680
      {
4681
	my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
4682
	error= -1;
4683
      }
4684
      else
4685
      {
4686
	*fn_ext(new_name)=0;
4687
	if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
4688
	  error= -1;
4689
        else if (0)
4690
      {
4691
          VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
4692
                                  table_name, 0));
4693
          error= -1;
4694
      }
4695
    }
4696
  }
4697
4698
    if (error == HA_ERR_WRONG_COMMAND)
4699
  {
4700
      error= 0;
4701
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4702
			  ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4703
			  table->alias);
4704
  }
4705
4706
    if (!error)
4707
    {
55 by brian
Update for using real bool types.
4708
      write_bin_log(thd, true, thd->query, thd->query_length);
1 by brian
clean slate
4709
      my_ok(thd);
4710
  }
4711
    else if (error > 0)
4712
  {
4713
      table->file->print_error(error, MYF(0));
4714
      error= -1;
4715
    }
4716
    if (name_lock)
55 by brian
Update for using real bool types.
4717
      unlink_open_table(thd, name_lock, false);
1 by brian
clean slate
4718
    VOID(pthread_mutex_unlock(&LOCK_open));
4719
    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
4720
    return(error);
1 by brian
clean slate
4721
  }
4722
4723
  /* We have to do full alter table. */
4724
4725
    /*
4726
    If the old table had partitions and we are doing ALTER TABLE ...
4727
    engine= <new_engine>, the new table must preserve the original
4728
    partitioning. That means that the new engine is still the
4729
    partitioning engine, not the engine specified in the parser.
4730
    This is discovered  in prep_alter_part_table, which in such case
4731
    updates create_info->db_type.
4732
    Now we need to update the stack copy of create_info->db_type,
4733
    as otherwise we won't be able to correctly move the files of the
4734
    temporary table to the result table files.
4735
  */
4736
  new_db_type= create_info->db_type;
4737
4738
  if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4739
      goto err;
4740
4741
  set_table_default_charset(thd, create_info, db);
4742
4743
4744
  if (thd->variables.old_alter_table
4745
      || (table->s->db_type() != create_info->db_type)
4746
     )
4747
  {
4748
    if (alter_info->build_method == HA_BUILD_ONLINE)
4749
    {
4750
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4751
      goto err;
4752
    }
4753
    alter_info->build_method= HA_BUILD_OFFLINE;
4754
  }
4755
4756
  if (alter_info->build_method != HA_BUILD_OFFLINE)
4757
  {
4758
    TABLE *altered_table= 0;
4759
    HA_ALTER_INFO ha_alter_info;
4760
    HA_ALTER_FLAGS ha_alter_flags;
4761
    uint table_changes= IS_EQUAL_YES;
55 by brian
Update for using real bool types.
4762
    bool need_copy_table= true;
1 by brian
clean slate
4763
    /* Check how much the tables differ. */
4764
    if (compare_tables(thd, table, alter_info,
4765
                       create_info, order_num,
4766
                       &ha_alter_flags,
4767
                       &ha_alter_info,
4768
                       &table_changes))
4769
    {
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
4770
      return(true);
1 by brian
clean slate
4771
    }
4772
4773
    /*
4774
      Check if storage engine supports altering the table
4775
      on-line.
4776
    */
4777
4778
4779
    /*
4780
      If table is not renamed, changed database and
4781
      some change was detected then check if engine
4782
      can do the change on-line
4783
    */
4784
    if (new_name == table_name && new_db == db &&
4785
        ha_alter_flags.is_set())
4786
    {
4787
      Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4788
4789
      /*
4790
        If no table rename,
4791
        check if table can be altered on-line
4792
      */
4793
      if (!(altered_table= create_altered_table(thd,
4794
                                                table,
4795
                                                new_db,
4796
                                                create_info,
4797
                                                &tmp_alter_info,
4798
                                                !strcmp(db, new_db))))
4799
        goto err;
4800
4801
      switch (table->file->check_if_supported_alter(altered_table,
4802
                                                    create_info,
4803
                                                    &ha_alter_flags,
4804
                                                    table_changes)) {
4805
      case HA_ALTER_SUPPORTED_WAIT_LOCK:
4806
      case HA_ALTER_SUPPORTED_NO_LOCK:
4807
        /*
4808
          @todo: Currently we always acquire an exclusive name
4809
          lock on the table metadata when performing fast or online
4810
          ALTER TABLE. In future we may consider this unnecessary,
4811
          and narrow the scope of the exclusive name lock to only
4812
          cover manipulation with .frms. Storage engine API
4813
          call check_if_supported_alter has provision for this
4814
          already now.
4815
        */
55 by brian
Update for using real bool types.
4816
        need_copy_table= false;
1 by brian
clean slate
4817
        break;
4818
      case HA_ALTER_NOT_SUPPORTED:
4819
        if (alter_info->build_method == HA_BUILD_ONLINE)
4820
        {
4821
          my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4822
          close_temporary_table(thd, altered_table, 1, 1);
4823
          goto err;
4824
        }
55 by brian
Update for using real bool types.
4825
        need_copy_table= true;
1 by brian
clean slate
4826
        break;
4827
      case HA_ALTER_ERROR:
4828
      default:
4829
        close_temporary_table(thd, altered_table, 1, 1);
4830
        goto err;
4831
      }
4832
4833
    }
4834
    /* TODO need to check if changes can be handled as fast ALTER TABLE */
4835
    if (!altered_table)
55 by brian
Update for using real bool types.
4836
      need_copy_table= true;
1 by brian
clean slate
4837
4838
    if (!need_copy_table)
4839
    {
4840
      error= mysql_fast_or_online_alter_table(thd,
4841
                                              table,
4842
                                              altered_table,
4843
                                              create_info,
4844
                                              &ha_alter_info,
4845
                                              &ha_alter_flags,
4846
                                              alter_info->keys_onoff);
4847
      if (thd->lock)
4848
      {
4849
        mysql_unlock_tables(thd, thd->lock);
4850
        thd->lock=0;
4851
      }
4852
      close_temporary_table(thd, altered_table, 1, 1);
4853
4854
      if (error)
4855
      {
4856
        switch (error) {
4857
        case(-1):
4858
          goto err_with_placeholders;
4859
        default:
4860
          goto err;
4861
        }
4862
      }
4863
      else
4864
      {
4865
        pthread_mutex_lock(&LOCK_open);
4866
        goto end_online;
4867
      }
4868
    }
4869
4870
    if (altered_table)
4871
      close_temporary_table(thd, altered_table, 1, 1);
4872
  }
4873
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
4874
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4875
           current_pid, thd->thread_id);
1 by brian
clean slate
4876
  /* Safety fix for innodb */
4877
  if (lower_case_table_names)
4878
    my_casedn_str(files_charset_info, tmp_name);
4879
4880
4881
  /* Create a temporary table with the new format */
4882
  if ((error= create_temporary_table(thd, table, new_db, tmp_name, 
4883
                                     create_info, alter_info, 
4884
                                     !strcmp(db, new_db))))
4885
  {
4886
    goto err;
4887
  }
4888
4889
  /* Open the table so we need to copy the data to it. */
4890
  if (table->s->tmp_table)
4891
  {
4892
    TABLE_LIST tbl;
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
4893
    memset((void*) &tbl, 0, sizeof(tbl));
1 by brian
clean slate
4894
    tbl.db= new_db;
4895
    tbl.table_name= tbl.alias= tmp_name;
4896
    /* Table is in thd->temporary_tables */
4897
    new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
4898
                          MYSQL_LOCK_IGNORE_FLUSH);
4899
  }
4900
  else
4901
  {
4902
    char path[FN_REFLEN];
4903
    /* table is a normal table: Create temporary table in same directory */
4904
    build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4905
                         FN_IS_TMP);
4906
    /* Open our intermediate table */
4907
    new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4908
  }
4909
  if (!new_table)
4910
    goto err1;
4911
4912
  /* Copy the data if necessary. */
4913
  thd->count_cuted_fields= CHECK_FIELD_WARN;	// calc cuted fields
4914
  thd->cuted_fields=0L;
4915
  thd_proc_info(thd, "copy to tmp table");
4916
  copied=deleted=0;
4917
  /*
4918
    We do not copy data for MERGE tables. Only the children have data.
4919
    MERGE tables have HA_NO_COPY_ON_ALTER set.
4920
  */
4921
  if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
4922
  {
4923
    /* We don't want update TIMESTAMP fields during ALTER TABLE. */
4924
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
4925
    new_table->next_number_field=new_table->found_next_number_field;
4926
    error= copy_data_between_tables(table, new_table,
4927
                                    alter_info->create_list, ignore,
4928
                                   order_num, order, &copied, &deleted,
4929
                                    alter_info->keys_onoff,
4930
                                    alter_info->error_if_not_empty);
4931
  }
4932
  else
4933
  {
4934
    VOID(pthread_mutex_lock(&LOCK_open));
4935
    wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4936
    VOID(pthread_mutex_unlock(&LOCK_open));
4937
    alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4938
                            alter_info->keys_onoff);
4939
    error= ha_autocommit_or_rollback(thd, 0);
4940
    if (end_active_trans(thd))
4941
      error= 1;
4942
  }
4943
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
4944
4945
  if (table->s->tmp_table != NO_TMP_TABLE)
4946
  {
4947
    /* We changed a temporary table */
4948
    if (error)
4949
      goto err1;
4950
    /* Close lock if this is a transactional table */
4951
    if (thd->lock)
4952
    {
4953
      mysql_unlock_tables(thd, thd->lock);
4954
      thd->lock=0;
4955
    }
4956
    /* Remove link to old table and rename the new one */
4957
    close_temporary_table(thd, table, 1, 1);
4958
    /* Should pass the 'new_name' as we store table name in the cache */
4959
    if (rename_temporary_table(thd, new_table, new_db, new_name))
4960
      goto err1;
4961
    /* We don't replicate alter table statement on temporary tables */
4962
    if (!thd->current_stmt_binlog_row_based)
55 by brian
Update for using real bool types.
4963
      write_bin_log(thd, true, thd->query, thd->query_length);
1 by brian
clean slate
4964
    goto end_temporary;
4965
  }
4966
4967
  if (new_table)
4968
  {
4969
    /*
4970
      Close the intermediate table that will be the new table.
4971
      Note that MERGE tables do not have their children attached here.
4972
    */
4973
    intern_close_table(new_table);
4974
    my_free(new_table,MYF(0));
4975
  }
4976
  VOID(pthread_mutex_lock(&LOCK_open));
4977
  if (error)
4978
  {
4979
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4980
    VOID(pthread_mutex_unlock(&LOCK_open));
4981
    goto err;
4982
  }
4983
4984
  /*
4985
    Data is copied. Now we:
4986
    1) Wait until all other threads close old version of table.
4987
    2) Close instances of table open by this thread and replace them
4988
       with exclusive name-locks.
4989
    3) Rename the old table to a temp name, rename the new one to the
4990
       old name.
4991
    4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
4992
       we reopen new version of table.
4993
    5) Write statement to the binary log.
4994
    6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
4995
       remove name-locks from list of open tables and table cache.
4996
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4997
       call to remove name-locks from table cache and list of open table.
4998
  */
4999
5000
  thd_proc_info(thd, "rename result table");
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
5001
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
5002
           current_pid, thd->thread_id);
1 by brian
clean slate
5003
  if (lower_case_table_names)
5004
    my_casedn_str(files_charset_info, old_name);
5005
5006
  wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
5007
  close_data_files_and_morph_locks(thd, db, table_name);
5008
5009
  error=0;
5010
  save_old_db_type= old_db_type;
5011
5012
  /*
5013
    This leads to the storage engine (SE) not being notified for renames in
5014
    mysql_rename_table(), because we just juggle with the FRM and nothing
5015
    more. If we have an intermediate table, then we notify the SE that
5016
    it should become the actual table. Later, we will recycle the old table.
5017
    However, in case of ALTER TABLE RENAME there might be no intermediate
5018
    table. This is when the old and new tables are compatible, according to
5019
    compare_table(). Then, we need one additional call to
5020
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
5021
    actual rename in the SE and the FRM is not touched. Note that, if the
5022
    table is renamed and the SE is also changed, then an intermediate table
5023
    is created and the additional call will not take place.
5024
  */
5025
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
5026
                         FN_TO_IS_TMP))
5027
  {
5028
    error=1;
5029
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5030
  }
5031
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
5032
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
5033
  {
5034
    /* Try to get everything back. */
5035
    error=1;
5036
    VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
5037
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5038
    VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
5039
                            FN_FROM_IS_TMP));
5040
  }
5041
5042
  if (error)
5043
  {
5044
    /* This shouldn't happen. But let us play it safe. */
5045
    goto err_with_placeholders;
5046
  }
5047
5048
  VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
5049
5050
end_online:
5051
  if (thd->locked_tables && new_name == table_name && new_db == db)
5052
  {
5053
    thd->in_lock_tables= 1;
5054
    error= reopen_tables(thd, 1, 1);
5055
    thd->in_lock_tables= 0;
5056
    if (error)
5057
      goto err_with_placeholders;
5058
  }
5059
  VOID(pthread_mutex_unlock(&LOCK_open));
5060
5061
  thd_proc_info(thd, "end");
5062
5063
  ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
5064
                      thd->query, thd->query_length,
5065
                      db, table_name);
5066
51.2.1 by Patrick Galbraith
Removed DBUG_PRINTs, DBUG_ASSERTs, DBUG_EXECUTE_IFs from
5067
  assert(!(mysql_bin_log.is_open() &&
1 by brian
clean slate
5068
                thd->current_stmt_binlog_row_based &&
5069
                (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
55 by brian
Update for using real bool types.
5070
  write_bin_log(thd, true, thd->query, thd->query_length);
1 by brian
clean slate
5071
5072
  if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
5073
  {
5074
    /*
5075
      For the alter table to be properly flushed to the logs, we
5076
      have to open the new table.  If not, we get a problem on server
5077
      shutdown. But we do not need to attach MERGE children.
5078
    */
5079
    char path[FN_REFLEN];
5080
    TABLE *t_table;
5081
    build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
55 by brian
Update for using real bool types.
5082
    t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
1 by brian
clean slate
5083
    if (t_table)
5084
    {
5085
      intern_close_table(t_table);
5086
      my_free(t_table, MYF(0));
5087
    }
5088
    else
5089
      sql_print_warning("Could not open table %s.%s after rename\n",
5090
                        new_db,table_name);
5091
    ha_flush_logs(old_db_type);
5092
  }
5093
  table_list->table=0;				// For query cache
5094
5095
  if (thd->locked_tables && (new_name != table_name || new_db != db))
5096
  {
5097
    /*
5098
      If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
5099
      to remove placeholders for the old table and for the target table
5100
      from the list of open tables and table cache. If we are not under
5101
      LOCK TABLES we can rely on close_thread_tables() doing this job.
5102
    */
5103
    pthread_mutex_lock(&LOCK_open);
55 by brian
Update for using real bool types.
5104
    unlink_open_table(thd, table, false);
5105
    unlink_open_table(thd, name_lock, false);
1 by brian
clean slate
5106
    pthread_mutex_unlock(&LOCK_open);
5107
  }
5108
5109
end_temporary:
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
5110
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5111
           (ulong) (copied + deleted), (ulong) deleted,
5112
           (ulong) thd->cuted_fields);
1 by brian
clean slate
5113
  my_ok(thd, copied + deleted, 0L, tmp_name);
5114
  thd->some_tables_deleted=0;
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
5115
  return(false);
1 by brian
clean slate
5116
5117
err1:
5118
  if (new_table)
5119
  {
5120
    /* close_temporary_table() frees the new_table pointer. */
5121
    close_temporary_table(thd, new_table, 1, 1);
5122
  }
5123
  else
5124
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5125
5126
err:
5127
  /*
5128
    No default value was provided for a DATE/DATETIME field, the
5129
    current sql_mode doesn't allow the '0000-00-00' value and
5130
    the table to be altered isn't empty.
5131
    Report error here.
5132
  */
5133
  if (alter_info->error_if_not_empty && thd->row_count)
5134
  {
5135
    const char *f_val= 0;
236.1.25 by Monty Taylor
Fixed a few naming references.
5136
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
1 by brian
clean slate
5137
    switch (alter_info->datetime_field->sql_type)
5138
    {
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
5139
      case DRIZZLE_TYPE_NEWDATE:
1 by brian
clean slate
5140
        f_val= "0000-00-00";
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
5141
        t_type= DRIZZLE_TIMESTAMP_DATE;
1 by brian
clean slate
5142
        break;
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
5143
      case DRIZZLE_TYPE_DATETIME:
1 by brian
clean slate
5144
        f_val= "0000-00-00 00:00:00";
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
5145
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
1 by brian
clean slate
5146
        break;
5147
      default:
5148
        /* Shouldn't get here. */
51.2.1 by Patrick Galbraith
Removed DBUG_PRINTs, DBUG_ASSERTs, DBUG_EXECUTE_IFs from
5149
        assert(0);
1 by brian
clean slate
5150
    }
5151
    bool save_abort_on_warning= thd->abort_on_warning;
55 by brian
Update for using real bool types.
5152
    thd->abort_on_warning= true;
1 by brian
clean slate
5153
    make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
5154
                                 f_val, strlength(f_val), t_type,
5155
                                 alter_info->datetime_field->field_name);
5156
    thd->abort_on_warning= save_abort_on_warning;
5157
  }
5158
  if (name_lock)
5159
  {
5160
    pthread_mutex_lock(&LOCK_open);
55 by brian
Update for using real bool types.
5161
    unlink_open_table(thd, name_lock, false);
1 by brian
clean slate
5162
    pthread_mutex_unlock(&LOCK_open);
5163
  }
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
5164
  return(true);
1 by brian
clean slate
5165
5166
err_with_placeholders:
5167
  /*
5168
    An error happened while we were holding exclusive name-lock on table
5169
    being altered. To be safe under LOCK TABLES we should remove placeholders
5170
    from list of open tables list and table cache.
5171
  */
55 by brian
Update for using real bool types.
5172
  unlink_open_table(thd, table, false);
1 by brian
clean slate
5173
  if (name_lock)
55 by brian
Update for using real bool types.
5174
    unlink_open_table(thd, name_lock, false);
1 by brian
clean slate
5175
  VOID(pthread_mutex_unlock(&LOCK_open));
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
5176
  return(true);
1 by brian
clean slate
5177
}
5178
/* mysql_alter_table */
5179
5180
static int
5181
copy_data_between_tables(TABLE *from,TABLE *to,
5182
			 List<Create_field> &create,
5183
                         bool ignore,
5184
			 uint order_num, ORDER *order,
5185
			 ha_rows *copied,
5186
			 ha_rows *deleted,
5187
                         enum enum_enable_or_disable keys_onoff,
5188
                         bool error_if_not_empty)
5189
{
5190
  int error;
5191
  Copy_field *copy,*copy_end;
5192
  ulong found_count,delete_count;
5193
  THD *thd= current_thd;
5194
  uint length= 0;
5195
  SORT_FIELD *sortorder;
5196
  READ_RECORD info;
5197
  TABLE_LIST   tables;
5198
  List<Item>   fields;
5199
  List<Item>   all_fields;
5200
  ha_rows examined_rows;
5201
  bool auto_increment_field_copied= 0;
5202
  ulong save_sql_mode;
151 by Brian Aker
Ulonglong to uint64_t
5203
  uint64_t prev_insert_id;
1 by brian
clean slate
5204
5205
  /*
5206
    Turn off recovery logging since rollback of an alter table is to
5207
    delete the new table so there is no need to log the changes to it.
5208
    
5209
    This needs to be done before external_lock
5210
  */
55 by brian
Update for using real bool types.
5211
  error= ha_enable_transaction(thd, false);
1 by brian
clean slate
5212
  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
5213
    return(-1);
1 by brian
clean slate
5214
  
5215
  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
5216
    return(-1);				/* purecov: inspected */
1 by brian
clean slate
5217
5218
  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
5219
    return(-1);
1 by brian
clean slate
5220
5221
  /* We need external lock before we can disable/enable keys */
5222
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5223
5224
  /* We can abort alter table for any table type */
5225
  thd->abort_on_warning= !ignore;
5226
5227
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5228
  to->file->ha_start_bulk_insert(from->file->stats.records);
5229
5230
  save_sql_mode= thd->variables.sql_mode;
5231
5232
  List_iterator<Create_field> it(create);
5233
  Create_field *def;
5234
  copy_end=copy;
5235
  for (Field **ptr=to->field ; *ptr ; ptr++)
5236
  {
5237
    def=it++;
5238
    if (def->field)
5239
    {
5240
      if (*ptr == to->next_number_field)
5241
      {
55 by brian
Update for using real bool types.
5242
        auto_increment_field_copied= true;
1 by brian
clean slate
5243
        /*
5244
          If we are going to copy contents of one auto_increment column to
5245
          another auto_increment column it is sensible to preserve zeroes.
5246
          This condition also covers case when we are don't actually alter
5247
          auto_increment column.
5248
        */
5249
        if (def->field == from->found_next_number_field)
5250
          thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
5251
      }
5252
      (copy_end++)->set(*ptr,def->field,0);
5253
    }
5254
5255
  }
5256
5257
  found_count=delete_count=0;
5258
5259
  if (order)
5260
  {
5261
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
5262
    {
5263
      char warn_buff[MYSQL_ERRMSG_SIZE];
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
5264
      snprintf(warn_buff, sizeof(warn_buff), 
5265
               "ORDER BY ignored as there is a user-defined clustered index"
5266
               " in the table '%-.192s'", from->s->table_name.str);
1 by brian
clean slate
5267
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5268
                   warn_buff);
5269
    }
5270
    else
5271
    {
5272
      from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5273
                                                MYF(MY_FAE | MY_ZEROFILL));
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
5274
      memset((char *) &tables, 0, sizeof(tables));
1 by brian
clean slate
5275
      tables.table= from;
5276
      tables.alias= tables.table_name= from->s->table_name.str;
5277
      tables.db= from->s->db.str;
5278
      error= 1;
5279
5280
      if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5281
          setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5282
                      &tables, fields, all_fields, order) ||
5283
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5284
          (from->sort.found_records= filesort(thd, from, sortorder, length,
5285
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
5286
                                              1, &examined_rows)) ==
5287
          HA_POS_ERROR)
5288
        goto err;
5289
    }
5290
  };
5291
5292
  /* Tell handler that we have values for all columns in the to table */
5293
  to->use_all_columns();
5294
  init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5295
  if (ignore)
5296
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5297
  thd->row_count= 0;
5298
  restore_record(to, s->default_values);        // Create empty record
5299
  while (!(error=info.read_record(&info)))
5300
  {
5301
    if (thd->killed)
5302
    {
5303
      thd->send_kill_message();
5304
      error= 1;
5305
      break;
5306
    }
5307
    thd->row_count++;
5308
    /* Return error if source table isn't empty. */
5309
    if (error_if_not_empty)
5310
    {
5311
      error= 1;
5312
      break;
5313
    }
5314
    if (to->next_number_field)
5315
    {
5316
      if (auto_increment_field_copied)
55 by brian
Update for using real bool types.
5317
        to->auto_increment_field_not_null= true;
1 by brian
clean slate
5318
      else
5319
        to->next_number_field->reset();
5320
    }
5321
    
5322
    for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5323
    {
5324
      copy_ptr->do_copy(copy_ptr);
5325
    }
5326
    prev_insert_id= to->file->next_insert_id;
5327
    error=to->file->ha_write_row(to->record[0]);
55 by brian
Update for using real bool types.
5328
    to->auto_increment_field_not_null= false;
1 by brian
clean slate
5329
    if (error)
5330
    {
5331
      if (!ignore ||
5332
          to->file->is_fatal_error(error, HA_CHECK_DUP))
5333
      {
5334
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5335
         {
5336
           uint key_nr= to->file->get_dup_key(error);
5337
           if ((int) key_nr >= 0)
5338
           {
5339
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5340
             if (key_nr == 0 &&
5341
                 (to->key_info[0].key_part[0].field->flags &
5342
                  AUTO_INCREMENT_FLAG))
5343
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5344
             to->file->print_keydup_error(key_nr, err_msg);
5345
             break;
5346
           }
5347
         }
5348
5349
	to->file->print_error(error,MYF(0));
5350
	break;
5351
      }
5352
      to->file->restore_auto_increment(prev_insert_id);
5353
      delete_count++;
5354
    }
5355
    else
5356
      found_count++;
5357
  }
5358
  end_read_record(&info);
5359
  free_io_cache(from);
5360
  delete [] copy;				// This is never 0
5361
5362
  if (to->file->ha_end_bulk_insert() && error <= 0)
5363
  {
5364
    to->file->print_error(my_errno,MYF(0));
5365
    error=1;
5366
  }
5367
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5368
55 by brian
Update for using real bool types.
5369
  if (ha_enable_transaction(thd, true))
1 by brian
clean slate
5370
  {
5371
    error= 1;
5372
    goto err;
5373
  }
5374
5375
  /*
5376
    Ensure that the new table is saved properly to disk so that we
5377
    can do a rename
5378
  */
5379
  if (ha_autocommit_or_rollback(thd, 0))
5380
    error=1;
5381
  if (end_active_trans(thd))
5382
    error=1;
5383
5384
 err:
5385
  thd->variables.sql_mode= save_sql_mode;
5386
  thd->abort_on_warning= 0;
5387
  free_io_cache(from);
5388
  *copied= found_count;
5389
  *deleted=delete_count;
5390
  to->file->ha_release_auto_increment();
5391
  if (to->file->ha_external_lock(thd,F_UNLCK))
5392
    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
5393
  return(error > 0 ? -1 : 0);
1 by brian
clean slate
5394
}
5395
5396
5397
/*
5398
  Recreates tables by calling mysql_alter_table().
5399
5400
  SYNOPSIS
5401
    mysql_recreate_table()
5402
    thd			Thread handler
5403
    tables		Tables to recreate
5404
5405
 RETURN
5406
    Like mysql_alter_table().
5407
*/
5408
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
5409
{
5410
  HA_CREATE_INFO create_info;
5411
  Alter_info alter_info;
5412
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
5413
  assert(!table_list->next_global);
1 by brian
clean slate
5414
  /*
5415
    table_list->table has been closed and freed. Do not reference
5416
    uninitialized data. open_tables() could fail.
5417
  */
5418
  table_list->table= NULL;
5419
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
5420
  memset((char*) &create_info, 0, sizeof(create_info));
1 by brian
clean slate
5421
  create_info.row_type=ROW_TYPE_NOT_USED;
5422
  create_info.default_table_charset=default_charset_info;
5423
  /* Force alter table to recreate table */
5424
  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
5425
  return(mysql_alter_table(thd, NullS, NullS, &create_info,
1 by brian
clean slate
5426
                                table_list, &alter_info, 0,
5427
                                (ORDER *) 0, 0));
5428
}
5429
5430
5431
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
5432
                          HA_CHECK_OPT *check_opt)
5433
{
5434
  TABLE_LIST *table;
5435
  List<Item> field_list;
5436
  Item *item;
5437
  Protocol *protocol= thd->protocol;
5438
5439
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5440
  item->maybe_null= 1;
152 by Brian Aker
longlong replacement
5441
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
1 by brian
clean slate
5442
                                          MY_INT64_NUM_DECIMAL_DIGITS));
5443
  item->maybe_null= 1;
5444
  if (protocol->send_fields(&field_list,
5445
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
5446
    return(true);
1 by brian
clean slate
5447
5448
  /* Open one table after the other to keep lock time as short as possible. */
5449
  for (table= tables; table; table= table->next_local)
5450
  {
5451
    char table_name[NAME_LEN*2+2];
5452
    TABLE *t;
5453
5454
    strxmov(table_name, table->db ,".", table->table_name, NullS);
5455
5456
    t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5457
    thd->clear_error();			// these errors shouldn't get client
5458
5459
    protocol->prepare_for_resend();
5460
    protocol->store(table_name, system_charset_info);
5461
5462
    if (!t)
5463
    {
5464
      /* Table didn't exist */
5465
      protocol->store_null();
5466
      thd->clear_error();
5467
    }
5468
    else
5469
    {
5470
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5471
	  !(check_opt->flags & T_EXTEND))
151 by Brian Aker
Ulonglong to uint64_t
5472
	protocol->store((uint64_t)t->file->checksum());
1 by brian
clean slate
5473
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5474
	       (check_opt->flags & T_QUICK))
5475
	protocol->store_null();
5476
      else
5477
      {
5478
	/* calculating table's checksum */
5479
	ha_checksum crc= 0;
5480
        uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
5481
5482
        t->use_all_columns();
5483
5484
	if (t->file->ha_rnd_init(1))
5485
	  protocol->store_null();
5486
	else
5487
	{
5488
	  for (;;)
5489
	  {
5490
	    ha_checksum row_crc= 0;
5491
            int error= t->file->rnd_next(t->record[0]);
5492
            if (unlikely(error))
5493
            {
5494
              if (error == HA_ERR_RECORD_DELETED)
5495
                continue;
5496
              break;
5497
            }
5498
	    if (t->s->null_bytes)
5499
            {
5500
              /* fix undefined null bits */
5501
              t->record[0][t->s->null_bytes-1] |= null_mask;
5502
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
5503
                t->record[0][0] |= 1;
5504
5505
	      row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5506
            }
5507
5508
	    for (uint i= 0; i < t->s->fields; i++ )
5509
	    {
5510
	      Field *f= t->field[i];
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
5511
	      if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5512
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
1 by brian
clean slate
5513
	      {
5514
		String tmp;
5515
		f->val_str(&tmp);
5516
		row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
5517
	      }
5518
	      else
5519
		row_crc= my_checksum(row_crc, f->ptr,
5520
				     f->pack_length());
5521
	    }
5522
5523
	    crc+= row_crc;
5524
	  }
151 by Brian Aker
Ulonglong to uint64_t
5525
	  protocol->store((uint64_t)crc);
1 by brian
clean slate
5526
          t->file->ha_rnd_end();
5527
	}
5528
      }
5529
      thd->clear_error();
5530
      close_thread_tables(thd);
5531
      table->table=0;				// For query cache
5532
    }
5533
    if (protocol->write())
5534
      goto err;
5535
  }
5536
5537
  my_eof(thd);
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
5538
  return(false);
1 by brian
clean slate
5539
5540
 err:
5541
  close_thread_tables(thd);			// Shouldn't be needed
5542
  if (table)
5543
    table->table=0;
51.1.8 by Jay Pipes
Resolving conflicts for a few files regarding FALSE=>false
5544
  return(true);
1 by brian
clean slate
5545
}
5546
5547
static bool check_engine(THD *thd, const char *table_name,
5548
                         HA_CREATE_INFO *create_info)
5549
{
5550
  handlerton **new_engine= &create_info->db_type;
5551
  handlerton *req_engine= *new_engine;
5552
  bool no_substitution= 1;
5553
  if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5554
                                  no_substitution, 1)))
55 by brian
Update for using real bool types.
5555
    return true;
1 by brian
clean slate
5556
5557
  if (req_engine && req_engine != *new_engine)
5558
  {
5559
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5560
                       ER_WARN_USING_OTHER_HANDLER,
5561
                       ER(ER_WARN_USING_OTHER_HANDLER),
5562
                       ha_resolve_storage_engine_name(*new_engine),
5563
                       table_name);
5564
  }
5565
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5566
      ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5567
  {
5568
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5569
    {
5570
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5571
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
5572
      *new_engine= 0;
55 by brian
Update for using real bool types.
5573
      return true;
1 by brian
clean slate
5574
    }
5575
    *new_engine= myisam_hton;
5576
  }
55 by brian
Update for using real bool types.
5577
  return false;
1 by brian
clean slate
5578
}