~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Lee
  • Date: 2009-01-01 03:07:33 UTC
  • mto: (758.1.3 devel)
  • mto: This revision was merged to the branch mainline in revision 759.
  • Revision ID: lbieber@lbieber-desktop-20090101030733-fb411b55f07vij8q
more header file cleanup

Show diffs side-by-side

added added

removed removed

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