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