~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2008-10-14 21:20:42 UTC
  • mto: (511.1.4 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081014212042-tef3njx3368b6lwt
Override copy ctr and op= because we have pointer members.

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