~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2008-10-07 19:30:18 UTC
  • mfrom: (322.2.8 stdize-code)
  • mto: This revision was merged to the branch mainline in revision 491.
  • Revision ID: monty@inaugust.com-20081007193018-22fhaywc990akeqa
Merged code from Mats that I should have merged a while ago.

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
 
                                uint32_t select_field_count,
1452
 
                                bool is_if_not_exists)
 
1715
                                uint32_t select_field_count)
1453
1716
{
 
1717
  char          path[FN_REFLEN];
 
1718
  uint32_t          path_length;
 
1719
  const char    *alias;
1454
1720
  uint          db_options, key_count;
1455
 
  KeyInfo               *key_info_buffer;
 
1721
  KEY           *key_info_buffer;
 
1722
  handler       *file;
1456
1723
  bool          error= true;
1457
 
 
1458
1724
  /* Check for duplicate fields and check type of table to create */
1459
 
  if (not alter_info->create_list.elements)
 
1725
  if (!alter_info->create_list.elements)
1460
1726
  {
1461
1727
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1462
1728
               MYF(0));
1463
 
    return true;
 
1729
    return(true);
1464
1730
  }
1465
 
  assert(identifier.getTableName() == table_proto.name());
 
1731
  if (check_engine(thd, table_name, create_info))
 
1732
    return(true);
1466
1733
  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
 
 
 
1734
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1735
    db_options|=HA_OPTION_PACK_RECORD;
 
1736
  alias= table_case_name(create_info, table_name);
 
1737
  if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
 
1738
                              create_info->db_type)))
 
1739
  {
 
1740
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
1741
    return(true);
 
1742
  }
 
1743
 
 
1744
  set_table_default_charset(thd, create_info, (char*) db);
 
1745
 
 
1746
  if (mysql_prepare_create_table(thd, create_info, alter_info,
 
1747
                                 internal_tmp_table,
 
1748
                                 &db_options, file,
 
1749
                          &key_info_buffer, &key_count,
 
1750
                          select_field_count))
 
1751
    goto err;
 
1752
 
 
1753
      /* Check if table exists */
 
1754
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1755
  {
 
1756
    path_length= build_tmptable_filename(thd, path, sizeof(path));
 
1757
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
1758
  }
 
1759
  else  
 
1760
  {
 
1761
 #ifdef FN_DEVCHAR
 
1762
    /* check if the table name contains FN_DEVCHAR when defined */
 
1763
    if (strchr(alias, FN_DEVCHAR))
 
1764
    {
 
1765
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
 
1766
      return(true);
 
1767
    }
 
1768
#endif
 
1769
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
1770
                                      internal_tmp_table ? FN_IS_TMP : 0);
 
1771
  }
 
1772
 
 
1773
  /* Check if table already exists */
 
1774
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1775
      find_temporary_table(thd, db, table_name))
 
1776
  {
 
1777
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1778
    {
 
1779
      create_info->table_existed= 1;            // Mark that table existed
 
1780
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1781
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1782
                          alias);
 
1783
      error= 0;
 
1784
      goto err;
 
1785
    }
 
1786
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
 
1787
    goto err;
 
1788
  }
 
1789
 
 
1790
  pthread_mutex_lock(&LOCK_open);
 
1791
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1792
  {
 
1793
    if (!access(path,F_OK))
 
1794
    {
 
1795
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1796
        goto warn;
 
1797
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1798
      goto unlock_and_end;
 
1799
    }
 
1800
    /*
 
1801
      We don't assert here, but check the result, because the table could be
 
1802
      in the table definition cache and in the same time the .frm could be
 
1803
      missing from the disk, in case of manual intervention which deletes
 
1804
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1805
      Then she could create the table. This case is pretty obscure and
 
1806
      therefore we don't introduce a new error message only for it.
 
1807
    */
 
1808
    if (get_cached_table_share(db, alias))
 
1809
    {
 
1810
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1811
      goto unlock_and_end;
 
1812
    }
 
1813
  }
 
1814
 
 
1815
  /*
 
1816
    Check that table with given name does not already
 
1817
    exist in any storage engine. In such a case it should
 
1818
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1819
    unless user specified CREATE TABLE IF EXISTS
 
1820
    The LOCK_open mutex has been locked to make sure no
 
1821
    one else is attempting to discover the table. Since
 
1822
    it's not on disk as a frm file, no one could be using it!
 
1823
  */
 
1824
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1825
  {
 
1826
    bool create_if_not_exists =
 
1827
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1828
    int retcode = ha_table_exists_in_engine(thd, db, table_name);
 
1829
    switch (retcode)
 
1830
    {
 
1831
      case HA_ERR_NO_SUCH_TABLE:
 
1832
        /* Normal case, no table exists. we can go and create it */
 
1833
        break;
 
1834
      case HA_ERR_TABLE_EXIST:
 
1835
 
 
1836
      if (create_if_not_exists)
 
1837
        goto warn;
 
1838
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1839
      goto unlock_and_end;
 
1840
        break;
 
1841
      default:
 
1842
        my_error(retcode, MYF(0),table_name);
 
1843
        goto unlock_and_end;
 
1844
    }
 
1845
  }
 
1846
 
 
1847
  thd->set_proc_info("creating table");
 
1848
  create_info->table_existed= 0;                // Mark that table is created
 
1849
 
 
1850
#ifdef HAVE_READLINK
 
1851
  if (test_if_data_home_dir(create_info->data_file_name))
 
1852
  {
 
1853
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
 
1854
    goto unlock_and_end;
 
1855
  }
 
1856
  if (test_if_data_home_dir(create_info->index_file_name))
 
1857
  {
 
1858
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
 
1859
    goto unlock_and_end;
 
1860
  }
 
1861
 
 
1862
  if (!my_use_symdir)
 
1863
#endif /* HAVE_READLINK */
 
1864
  {
 
1865
    if (create_info->data_file_name)
 
1866
      push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1867
                   "DATA DIRECTORY option ignored");
 
1868
    if (create_info->index_file_name)
 
1869
      push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1870
                   "INDEX DIRECTORY option ignored");
 
1871
    create_info->data_file_name= create_info->index_file_name= 0;
 
1872
  }
 
1873
  create_info->table_options=db_options;
 
1874
 
 
1875
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
 
1876
  if (rea_create_table(thd, path, db, table_name,
 
1877
                       create_info, alter_info->create_list,
 
1878
                       key_count, key_info_buffer, file))
 
1879
    goto unlock_and_end;
 
1880
 
 
1881
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1882
  {
 
1883
    /* Open table and put in temporary table list */
 
1884
    if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
 
1885
    {
 
1886
      (void) rm_temporary_table(create_info->db_type, path, false);
 
1887
      goto unlock_and_end;
 
1888
    }
 
1889
    thd->thread_specific_used= true;
 
1890
  }
 
1891
 
 
1892
  /*
 
1893
    Don't write statement if:
 
1894
    - It is an internal temporary table,
 
1895
    - Row-based logging is used and it we are creating a temporary table, or
 
1896
    - The binary log is not open.
 
1897
    Otherwise, the statement shall be binlogged.
 
1898
   */
 
1899
  if (!internal_tmp_table &&
 
1900
      (!thd->current_stmt_binlog_row_based ||
 
1901
       (thd->current_stmt_binlog_row_based &&
 
1902
        !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1903
    write_bin_log(thd, true, thd->query, thd->query_length);
 
1904
  error= false;
 
1905
unlock_and_end:
 
1906
  pthread_mutex_unlock(&LOCK_open);
 
1907
 
 
1908
err:
 
1909
  thd->set_proc_info("After create");
 
1910
  delete file;
1491
1911
  return(error);
 
1912
 
 
1913
warn:
 
1914
  error= false;
 
1915
  push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1916
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1917
                      alias);
 
1918
  create_info->table_existed= 1;                // Mark that table existed
 
1919
  goto unlock_and_end;
1492
1920
}
1493
1921
 
1494
 
/**
1495
 
  @note the following two methods implement create [temporary] table.
 
1922
 
 
1923
/*
 
1924
  Database locking aware wrapper for mysql_create_table_no_lock(),
1496
1925
*/
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)
 
1926
 
 
1927
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
 
1928
                        HA_CREATE_INFO *create_info,
 
1929
                        Alter_info *alter_info,
 
1930
                        bool internal_tmp_table,
 
1931
                        uint32_t select_field_count)
1505
1932
{
1506
 
  Table *name_lock= NULL;
 
1933
  Table *name_lock= 0;
1507
1934
  bool result;
1508
1935
 
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);
 
1936
  /* Wait for any database locks */
 
1937
  pthread_mutex_lock(&LOCK_lock_db);
 
1938
  while (!thd->killed &&
 
1939
         hash_search(&lock_db_cache,(unsigned char*) db, strlen(db)))
 
1940
  {
 
1941
    wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
 
1942
    pthread_mutex_lock(&LOCK_lock_db);
 
1943
  }
 
1944
 
 
1945
  if (thd->killed)
 
1946
  {
 
1947
    pthread_mutex_unlock(&LOCK_lock_db);
 
1948
    return(true);
 
1949
  }
 
1950
  creating_table++;
 
1951
  pthread_mutex_unlock(&LOCK_lock_db);
 
1952
 
 
1953
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1954
  {
 
1955
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
1956
    {
1526
1957
      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
 
 
 
1958
      goto unlock;
 
1959
    }
 
1960
    if (!name_lock)
 
1961
    {
 
1962
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1963
      {
 
1964
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1965
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1966
                            table_name);
 
1967
        create_info->table_existed= 1;
 
1968
        result= false;
 
1969
      }
 
1970
      else
 
1971
      {
 
1972
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1973
        result= true;
 
1974
      }
 
1975
      goto unlock;
 
1976
    }
 
1977
  }
 
1978
 
 
1979
  result= mysql_create_table_no_lock(thd, db, table_name, create_info,
 
1980
                                     alter_info,
 
1981
                                     internal_tmp_table,
 
1982
                                     select_field_count);
 
1983
 
 
1984
unlock:
1541
1985
  if (name_lock)
1542
1986
  {
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);
 
1987
    pthread_mutex_lock(&LOCK_open);
 
1988
    unlink_open_table(thd, name_lock, false);
 
1989
    pthread_mutex_unlock(&LOCK_open);
1545
1990
  }
1546
 
 
 
1991
  pthread_mutex_lock(&LOCK_lock_db);
 
1992
  if (!--creating_table && creating_database)
 
1993
    pthread_cond_signal(&COND_refresh);
 
1994
  pthread_mutex_unlock(&LOCK_lock_db);
1547
1995
  return(result);
1548
1996
}
1549
1997
 
1550
1998
 
1551
1999
/*
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
2000
** Give the key name after the first field with an optional '_#' after
1588
2001
**/
1589
2002
 
1590
2003
static bool
1591
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
2004
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1592
2005
{
1593
 
  for (KeyInfo *key=start ; key != end ; key++)
 
2006
  for (KEY *key=start ; key != end ; key++)
1594
2007
    if (!my_strcasecmp(system_charset_info,name,key->name))
1595
2008
      return 1;
1596
2009
  return 0;
1598
2011
 
1599
2012
 
1600
2013
static char *
1601
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
2014
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1602
2015
{
1603
2016
  char buff[MAX_FIELD_NAME],*buff_end;
1604
2017
 
1605
2018
  if (!check_if_keyname_exists(field_name,start,end) &&
1606
 
      !is_primary_key_name(field_name))
 
2019
      my_strcasecmp(system_charset_info,field_name,primary_key_name))
1607
2020
    return (char*) field_name;                  // Use fieldname
1608
 
 
1609
 
  buff_end= strncpy(buff, field_name, sizeof(buff)-4);
1610
 
  buff_end+= strlen(buff);
 
2021
  buff_end=strmake(buff,field_name, sizeof(buff)-4);
1611
2022
 
1612
2023
  /*
1613
2024
    Only 3 chars + '\0' left, so need to limit to 2 digit
1616
2027
  for (uint32_t i=2 ; i< 100; i++)
1617
2028
  {
1618
2029
    *buff_end= '_';
1619
 
    internal::int10_to_str(i, buff_end+1, 10);
 
2030
    int10_to_str(i, buff_end+1, 10);
1620
2031
    if (!check_if_keyname_exists(buff,start,end))
1621
 
      return memory::sql_strdup(buff);
 
2032
      return sql_strdup(buff);
1622
2033
  }
1623
2034
  return (char*) "not_specified";               // Should never happen
1624
2035
}
1628
2039
** Alter a table definition
1629
2040
****************************************************************************/
1630
2041
 
 
2042
 
1631
2043
/*
1632
2044
  Rename a table.
1633
2045
 
1634
2046
  SYNOPSIS
1635
 
    rename_table()
1636
 
      session
1637
 
      base                      The plugin::StorageEngine handle.
 
2047
    mysql_rename_table()
 
2048
      base                      The handlerton handle.
1638
2049
      old_db                    The old database name.
1639
2050
      old_name                  The old table name.
1640
2051
      new_db                    The new database name.
1641
2052
      new_name                  The new table name.
 
2053
      flags                     flags for build_table_filename().
 
2054
                                FN_FROM_IS_TMP old_name is temporary.
 
2055
                                FN_TO_IS_TMP   new_name is temporary.
 
2056
                                NO_FRM_RENAME  Don't rename the FRM file
 
2057
                                but only the table in the storage engine.
1642
2058
 
1643
2059
  RETURN
1644
2060
    false   OK
1646
2062
*/
1647
2063
 
1648
2064
bool
1649
 
rename_table(Session &session,
1650
 
                   plugin::StorageEngine *base,
1651
 
                   const identifier::Table &from,
1652
 
                   const identifier::Table &to)
 
2065
mysql_rename_table(handlerton *base, const char *old_db,
 
2066
                   const char *old_name, const char *new_db,
 
2067
                   const char *new_name, uint32_t flags)
1653
2068
{
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
 
 
 
2069
  THD *thd= current_thd;
 
2070
  char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
 
2071
  char *from_base= from, *to_base= to;
 
2072
  char tmp_name[NAME_LEN+1];
 
2073
  handler *file;
 
2074
  int error=0;
 
2075
 
 
2076
  file= (base == NULL ? 0 :
 
2077
         get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
 
2078
 
 
2079
  build_table_filename(from, sizeof(from), old_db, old_name, "",
 
2080
                       flags & FN_FROM_IS_TMP);
 
2081
  build_table_filename(to, sizeof(to), new_db, new_name, "",
 
2082
                       flags & FN_TO_IS_TMP);
 
2083
 
 
2084
  /*
 
2085
    If lower_case_table_names == 2 (case-preserving but case-insensitive
 
2086
    file system) and the storage is not HA_FILE_BASED, we need to provide
 
2087
    a lowercase file name, but we leave the .frm in mixed case.
 
2088
   */
 
2089
  if (lower_case_table_names == 2 && file &&
 
2090
      !(file->ha_table_flags() & HA_FILE_BASED))
 
2091
  {
 
2092
    my_stpcpy(tmp_name, old_name);
 
2093
    my_casedn_str(files_charset_info, tmp_name);
 
2094
    build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
 
2095
                         flags & FN_FROM_IS_TMP);
 
2096
    from_base= lc_from;
 
2097
 
 
2098
    my_stpcpy(tmp_name, new_name);
 
2099
    my_casedn_str(files_charset_info, tmp_name);
 
2100
    build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
 
2101
                         flags & FN_TO_IS_TMP);
 
2102
    to_base= lc_to;
 
2103
  }
 
2104
  if (!file || !(error=file->ha_rename_table(from_base, to_base)))
 
2105
  {
 
2106
    if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
 
2107
    {
 
2108
      error=my_errno;
 
2109
      /* Restore old file name */
 
2110
      if (file)
 
2111
        file->ha_rename_table(to_base, from_base);
 
2112
    }
 
2113
  }
 
2114
  delete file;
1666
2115
  if (error == HA_ERR_WRONG_COMMAND)
1667
 
  {
1668
2116
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1669
 
  }
1670
2117
  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; 
 
2118
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
2119
  return(error != 0);
1685
2120
}
1686
2121
 
1687
2122
 
1690
2125
 
1691
2126
  SYNOPSIS
1692
2127
    wait_while_table_is_used()
1693
 
    session                     Thread Cursor
 
2128
    thd                 Thread handler
1694
2129
    table               Table to remove from cache
1695
2130
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1696
2131
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1700
2135
   the table is closed.
1701
2136
 
1702
2137
  PREREQUISITES
1703
 
    Lock on table::Cache::singleton().mutex()
 
2138
    Lock on LOCK_open
1704
2139
    Win32 clients must also have a WRITE LOCK on the table !
1705
2140
*/
1706
2141
 
1707
 
void wait_while_table_is_used(Session *session, Table *table,
 
2142
void wait_while_table_is_used(THD *thd, Table *table,
1708
2143
                              enum ha_extra_function function)
1709
2144
{
1710
2145
 
1711
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
2146
  safe_mutex_assert_owner(&LOCK_open);
1712
2147
 
1713
 
  table->cursor->extra(function);
 
2148
  table->file->extra(function);
1714
2149
  /* Mark all tables that are in use as 'old' */
1715
 
  session->abortLock(table);    /* end threads waiting on lock */
 
2150
  mysql_lock_abort(thd, table, true);   /* end threads waiting on lock */
1716
2151
 
1717
2152
  /* 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);
 
2153
  remove_table_from_cache(thd, table->s->db.str,
 
2154
                          table->s->table_name.str,
 
2155
                          RTFC_WAIT_OTHER_THREAD_FLAG);
 
2156
  return;
1720
2157
}
1721
2158
 
1722
2159
/*
1724
2161
 
1725
2162
  SYNOPSIS
1726
2163
    close_cached_table()
1727
 
    session                     Thread Cursor
 
2164
    thd                 Thread handler
1728
2165
    table               Table to remove from cache
1729
2166
 
1730
2167
  NOTES
1732
2169
    reopen the table.
1733
2170
 
1734
2171
  PREREQUISITES
1735
 
    Lock on table::Cache::singleton().mutex()
 
2172
    Lock on LOCK_open
1736
2173
    Win32 clients must also have a WRITE LOCK on the table !
1737
2174
*/
1738
2175
 
1739
 
void Session::close_cached_table(Table *table)
 
2176
void close_cached_table(THD *thd, Table *table)
1740
2177
{
1741
2178
 
1742
 
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
 
2179
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
1743
2180
  /* Close lock if this is not got with LOCK TABLES */
1744
 
  if (lock)
 
2181
  if (thd->lock)
1745
2182
  {
1746
 
    unlockTables(lock);
1747
 
    lock= NULL;                 // Start locked threads
 
2183
    mysql_unlock_tables(thd, thd->lock);
 
2184
    thd->lock=0;                        // Start locked threads
1748
2185
  }
1749
2186
  /* 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
 
}
 
2187
  unlink_open_table(thd, table, true);
 
2188
 
 
2189
  /* When lock on LOCK_open is freed other threads can continue */
 
2190
  broadcast_refresh();
 
2191
  return;
 
2192
}
 
2193
 
 
2194
static int send_check_errmsg(THD *thd, TableList* table,
 
2195
                             const char* operator_name, const char* errmsg)
 
2196
 
 
2197
{
 
2198
  Protocol *protocol= thd->protocol;
 
2199
  protocol->prepare_for_resend();
 
2200
  protocol->store(table->alias, system_charset_info);
 
2201
  protocol->store((char*) operator_name, system_charset_info);
 
2202
  protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2203
  protocol->store(errmsg, system_charset_info);
 
2204
  thd->clear_error();
 
2205
  if (protocol->write())
 
2206
    return -1;
 
2207
  return 1;
 
2208
}
 
2209
 
 
2210
 
 
2211
static int prepare_for_repair(THD *thd, TableList *table_list,
 
2212
                              HA_CHECK_OPT *check_opt)
 
2213
{
 
2214
  int error= 0;
 
2215
  Table tmp_table, *table;
 
2216
  TABLE_SHARE *share;
 
2217
  char from[FN_REFLEN],tmp[FN_REFLEN+32];
 
2218
  const char **ext;
 
2219
  struct stat stat_info;
 
2220
 
 
2221
  if (!(check_opt->sql_flags & TT_USEFRM))
 
2222
    return(0);
 
2223
 
 
2224
  if (!(table= table_list->table))              /* if open_ltable failed */
 
2225
  {
 
2226
    char key[MAX_DBKEY_LENGTH];
 
2227
    uint32_t key_length;
 
2228
 
 
2229
    key_length= create_table_def_key(thd, key, table_list, 0);
 
2230
    pthread_mutex_lock(&LOCK_open);
 
2231
    if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
 
2232
                                  &error))))
 
2233
    {
 
2234
      pthread_mutex_unlock(&LOCK_open);
 
2235
      return(0);                                // Can't open frm file
 
2236
    }
 
2237
 
 
2238
    if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
 
2239
    {
 
2240
      release_table_share(share, RELEASE_NORMAL);
 
2241
      pthread_mutex_unlock(&LOCK_open);
 
2242
      return(0);                           // Out of memory
 
2243
    }
 
2244
    table= &tmp_table;
 
2245
    pthread_mutex_unlock(&LOCK_open);
 
2246
  }
 
2247
 
 
2248
  /*
 
2249
    REPAIR Table ... USE_FRM for temporary tables makes little sense.
 
2250
  */
 
2251
  if (table->s->tmp_table)
 
2252
  {
 
2253
    error= send_check_errmsg(thd, table_list, "repair",
 
2254
                             "Cannot repair temporary table from .frm file");
 
2255
    goto end;
 
2256
  }
 
2257
 
 
2258
  /*
 
2259
    User gave us USE_FRM which means that the header in the index file is
 
2260
    trashed.
 
2261
    In this case we will try to fix the table the following way:
 
2262
    - Rename the data file to a temporary name
 
2263
    - Truncate the table
 
2264
    - Replace the new data file with the old one
 
2265
    - Run a normal repair using the new index file and the old data file
 
2266
  */
 
2267
 
 
2268
  /*
 
2269
    Check if this is a table type that stores index and data separately,
 
2270
    like ISAM or MyISAM. We assume fixed order of engine file name
 
2271
    extentions array. First element of engine file name extentions array
 
2272
    is meta/index file extention. Second element - data file extention. 
 
2273
  */
 
2274
  ext= table->file->bas_ext();
 
2275
  if (!ext[0] || !ext[1])
 
2276
    goto end;                                   // No data file
 
2277
 
 
2278
  // Name of data file
 
2279
  strxmov(from, table->s->normalized_path.str, ext[1], NULL);
 
2280
  if (stat(from, &stat_info))
 
2281
    goto end;                           // Can't use USE_FRM flag
 
2282
 
 
2283
  snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
 
2284
           from, current_pid, thd->thread_id);
 
2285
 
 
2286
  /* If we could open the table, close it */
 
2287
  if (table_list->table)
 
2288
  {
 
2289
    pthread_mutex_lock(&LOCK_open);
 
2290
    close_cached_table(thd, table);
 
2291
    pthread_mutex_unlock(&LOCK_open);
 
2292
  }
 
2293
  if (lock_and_wait_for_table_name(thd,table_list))
 
2294
  {
 
2295
    error= -1;
 
2296
    goto end;
 
2297
  }
 
2298
  if (my_rename(from, tmp, MYF(MY_WME)))
 
2299
  {
 
2300
    pthread_mutex_lock(&LOCK_open);
 
2301
    unlock_table_name(thd, table_list);
 
2302
    pthread_mutex_unlock(&LOCK_open);
 
2303
    error= send_check_errmsg(thd, table_list, "repair",
 
2304
                             "Failed renaming data file");
 
2305
    goto end;
 
2306
  }
 
2307
  if (mysql_truncate(thd, table_list, 1))
 
2308
  {
 
2309
    pthread_mutex_lock(&LOCK_open);
 
2310
    unlock_table_name(thd, table_list);
 
2311
    pthread_mutex_unlock(&LOCK_open);
 
2312
    error= send_check_errmsg(thd, table_list, "repair",
 
2313
                             "Failed generating table from .frm file");
 
2314
    goto end;
 
2315
  }
 
2316
  if (my_rename(tmp, from, MYF(MY_WME)))
 
2317
  {
 
2318
    pthread_mutex_lock(&LOCK_open);
 
2319
    unlock_table_name(thd, table_list);
 
2320
    pthread_mutex_unlock(&LOCK_open);
 
2321
    error= send_check_errmsg(thd, table_list, "repair",
 
2322
                             "Failed restoring .MYD file");
 
2323
    goto end;
 
2324
  }
 
2325
 
 
2326
  /*
 
2327
    Now we should be able to open the partially repaired table
 
2328
    to finish the repair in the handler later on.
 
2329
  */
 
2330
  pthread_mutex_lock(&LOCK_open);
 
2331
  if (reopen_name_locked_table(thd, table_list, true))
 
2332
  {
 
2333
    unlock_table_name(thd, table_list);
 
2334
    pthread_mutex_unlock(&LOCK_open);
 
2335
    error= send_check_errmsg(thd, table_list, "repair",
 
2336
                             "Failed to open partially repaired table");
 
2337
    goto end;
 
2338
  }
 
2339
  pthread_mutex_unlock(&LOCK_open);
 
2340
 
 
2341
end:
 
2342
  if (table == &tmp_table)
 
2343
  {
 
2344
    pthread_mutex_lock(&LOCK_open);
 
2345
    closefrm(table, 1);                         // Free allocated memory
 
2346
    pthread_mutex_unlock(&LOCK_open);
 
2347
  }
 
2348
  return(error);
 
2349
}
 
2350
 
 
2351
 
1755
2352
 
1756
2353
/*
1757
2354
  RETURN VALUES
1758
2355
    false Message sent to net (admin operation went ok)
1759
 
    true  Message should be sent by caller
 
2356
    true  Message should be sent by caller 
1760
2357
          (admin operation or network communication failed)
1761
2358
*/
1762
 
static bool admin_table(Session* session, TableList* tables,
 
2359
static bool mysql_admin_table(THD* thd, TableList* tables,
1763
2360
                              HA_CHECK_OPT* check_opt,
1764
2361
                              const char *operator_name,
1765
2362
                              thr_lock_type lock_type,
1766
2363
                              bool open_for_modify,
1767
 
                              int (Cursor::*operator_func)(Session *,
 
2364
                              bool no_warnings_for_error,
 
2365
                              uint32_t extra_open_options,
 
2366
                              int (*prepare_func)(THD *, TableList *,
 
2367
                                                  HA_CHECK_OPT *),
 
2368
                              int (handler::*operator_func)(THD *,
1768
2369
                                                            HA_CHECK_OPT *))
1769
2370
{
1770
2371
  TableList *table;
1771
 
  Select_Lex *select= &session->getLex()->select_lex;
 
2372
  SELECT_LEX *select= &thd->lex->select_lex;
1772
2373
  List<Item> field_list;
1773
2374
  Item *item;
 
2375
  Protocol *protocol= thd->protocol;
 
2376
  LEX *lex= thd->lex;
1774
2377
  int result_code= 0;
1775
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1776
2378
  const CHARSET_INFO * const cs= system_charset_info;
1777
2379
 
1778
 
  if (! session->endActiveTransaction())
1779
 
    return 1;
1780
 
 
 
2380
  if (end_active_trans(thd))
 
2381
    return(1);
1781
2382
  field_list.push_back(item = new Item_empty_string("Table",
1782
2383
                                                    NAME_CHAR_LEN * 2,
1783
2384
                                                    cs));
1788
2389
  item->maybe_null = 1;
1789
2390
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1790
2391
  item->maybe_null = 1;
1791
 
  if (session->getClient()->sendFields(&field_list))
1792
 
    return true;
 
2392
  if (protocol->send_fields(&field_list,
 
2393
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
2394
    return(true);
 
2395
 
 
2396
  mysql_ha_rm_tables(thd, tables, false);
1793
2397
 
1794
2398
  for (table= tables; table; table= table->next_local)
1795
2399
  {
1796
 
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
 
    std::string table_name;
 
2400
    char table_name[NAME_LEN*2+2];
 
2401
    char* db = table->db;
1798
2402
    bool fatal_error=0;
1799
2403
 
1800
 
    table_identifier.getSQLPath(table_name);
1801
 
 
 
2404
    strxmov(table_name, db, ".", table->table_name, NULL);
 
2405
    thd->open_options|= extra_open_options;
1802
2406
    table->lock_type= lock_type;
1803
2407
    /* open only one table from local list of command */
1804
2408
    {
1811
2415
      /*
1812
2416
        Time zone tables and SP tables can be add to lex->query_tables list,
1813
2417
        so it have to be prepared.
1814
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2418
        TODO: Investigate if we can put extra tables into argument instead of
 
2419
        using lex->query_tables
1815
2420
      */
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;
 
2421
      lex->query_tables= table;
 
2422
      lex->query_tables_last= &table->next_global;
 
2423
      lex->query_tables_own_last= 0;
 
2424
      thd->no_warnings_for_error= no_warnings_for_error;
1820
2425
 
1821
 
      session->openTablesLock(table);
1822
 
      session->no_warnings_for_error= 0;
 
2426
      open_and_lock_tables(thd, table);
 
2427
      thd->no_warnings_for_error= 0;
1823
2428
      table->next_global= save_next_global;
1824
2429
      table->next_local= save_next_local;
 
2430
      thd->open_options&= ~extra_open_options;
 
2431
    }
 
2432
 
 
2433
    if (prepare_func)
 
2434
    {
 
2435
      switch ((*prepare_func)(thd, table, check_opt)) {
 
2436
      case  1:           // error, message written to net
 
2437
        ha_autocommit_or_rollback(thd, 1);
 
2438
        end_trans(thd, ROLLBACK);
 
2439
        close_thread_tables(thd);
 
2440
        continue;
 
2441
      case -1:           // error, message could be written to net
 
2442
        /* purecov: begin inspected */
 
2443
        goto err;
 
2444
        /* purecov: end */
 
2445
      default:           // should be 0 otherwise
 
2446
        ;
 
2447
      }
1825
2448
    }
1826
2449
 
1827
2450
    /*
1834
2457
    */
1835
2458
    if (!table->table)
1836
2459
    {
1837
 
      if (!session->warn_list.elements)
1838
 
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2460
      if (!thd->warn_list.elements)
 
2461
        push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1839
2462
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1840
 
      result_code= HA_ADMIN_CORRUPT;
1841
2463
      goto send_result;
1842
2464
    }
1843
2465
 
1844
2466
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
1845
2467
    {
 
2468
      /* purecov: begin inspected */
1846
2469
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
2470
      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"));
 
2471
      protocol->prepare_for_resend();
 
2472
      protocol->store(table_name, system_charset_info);
 
2473
      protocol->store(operator_name, system_charset_info);
 
2474
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
1851
2475
      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);
 
2476
                       table_name);
 
2477
      protocol->store(buff, length, system_charset_info);
 
2478
      ha_autocommit_or_rollback(thd, 0);
 
2479
      end_trans(thd, COMMIT);
 
2480
      close_thread_tables(thd);
 
2481
      lex->reset_query_tables_list(false);
1858
2482
      table->table=0;                           // For query cache
1859
 
      if (session->getClient()->flush())
 
2483
      if (protocol->write())
1860
2484
        goto err;
1861
2485
      continue;
 
2486
      /* purecov: end */
1862
2487
    }
1863
2488
 
1864
2489
    /* Close all instances of the table to allow repair to rename files */
1865
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2490
    if (lock_type == TL_WRITE && table->table->s->version)
1866
2491
    {
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())
 
2492
      pthread_mutex_lock(&LOCK_open);
 
2493
      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 
2494
                                              "Waiting to get writelock");
 
2495
      mysql_lock_abort(thd,table->table, true);
 
2496
      remove_table_from_cache(thd, table->table->s->db.str,
 
2497
                              table->table->s->table_name.str,
 
2498
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2499
                              RTFC_CHECK_KILLED_FLAG);
 
2500
      thd->exit_cond(old_message);
 
2501
      if (thd->killed)
1875
2502
        goto err;
1876
2503
      open_for_modify= 0;
1877
2504
    }
1878
2505
 
1879
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
2506
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2507
    {
 
2508
      /* purecov: begin inspected */
 
2509
      protocol->prepare_for_resend();
 
2510
      protocol->store(table_name, system_charset_info);
 
2511
      protocol->store(operator_name, system_charset_info);
 
2512
      protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
 
2513
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
 
2514
                      system_charset_info);
 
2515
      if (protocol->write())
 
2516
        goto err;
 
2517
      /* purecov: end */
 
2518
    }
 
2519
 
 
2520
    if (operator_func == &handler::ha_repair &&
 
2521
        !(check_opt->sql_flags & TT_USEFRM))
 
2522
    {
 
2523
      if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
 
2524
          (table->table->file->ha_check_for_upgrade(check_opt) ==
 
2525
           HA_ADMIN_NEEDS_ALTER))
 
2526
      {
 
2527
        ha_autocommit_or_rollback(thd, 1);
 
2528
        close_thread_tables(thd);
 
2529
        tmp_disable_binlog(thd); // binlogging is done by caller if wanted
 
2530
        result_code= mysql_recreate_table(thd, table);
 
2531
        reenable_binlog(thd);
 
2532
        /*
 
2533
          mysql_recreate_table() can push OK or ERROR.
 
2534
          Clear 'OK' status. If there is an error, keep it:
 
2535
          we will store the error message in a result set row 
 
2536
          and then clear.
 
2537
        */
 
2538
        if (thd->main_da.is_ok())
 
2539
          thd->main_da.reset_diagnostics_area();
 
2540
        goto send_result;
 
2541
      }
 
2542
    }
 
2543
 
 
2544
    result_code = (table->table->file->*operator_func)(thd, check_opt);
1880
2545
 
1881
2546
send_result:
1882
2547
 
1883
 
    session->getLex()->cleanup_after_one_table_open();
1884
 
    session->clear_error();  // these errors shouldn't get client
 
2548
    lex->cleanup_after_one_table_open();
 
2549
    thd->clear_error();  // these errors shouldn't get client
1885
2550
    {
1886
 
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
 
2551
      List_iterator_fast<DRIZZLE_ERROR> it(thd->warn_list);
1887
2552
      DRIZZLE_ERROR *err;
1888
2553
      while ((err= it++))
1889
2554
      {
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())
 
2555
        protocol->prepare_for_resend();
 
2556
        protocol->store(table_name, system_charset_info);
 
2557
        protocol->store((char*) operator_name, system_charset_info);
 
2558
        protocol->store(warning_level_names[err->level].str,
 
2559
                        warning_level_names[err->level].length,
 
2560
                        system_charset_info);
 
2561
        protocol->store(err->msg, system_charset_info);
 
2562
        if (protocol->write())
1896
2563
          goto err;
1897
2564
      }
1898
 
      drizzle_reset_errors(session, true);
 
2565
      drizzle_reset_errors(thd, true);
1899
2566
    }
1900
 
    session->getClient()->store(table_name.c_str());
1901
 
    session->getClient()->store(operator_name);
 
2567
    protocol->prepare_for_resend();
 
2568
    protocol->store(table_name, system_charset_info);
 
2569
    protocol->store(operator_name, system_charset_info);
 
2570
 
 
2571
send_result_message:
1902
2572
 
1903
2573
    switch (result_code) {
1904
2574
    case HA_ADMIN_NOT_IMPLEMENTED:
1906
2576
        char buf[ERRMSGSIZE+20];
1907
2577
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
2578
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1910
 
        session->getClient()->store(buf, length);
 
2579
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
2580
        protocol->store(buf, length, system_charset_info);
 
2581
      }
 
2582
      break;
 
2583
 
 
2584
    case HA_ADMIN_NOT_BASE_TABLE:
 
2585
      {
 
2586
        char buf[ERRMSGSIZE+20];
 
2587
        uint32_t length= snprintf(buf, ERRMSGSIZE,
 
2588
                              ER(ER_BAD_TABLE_ERROR), table_name);
 
2589
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
2590
        protocol->store(buf, length, system_charset_info);
1911
2591
      }
1912
2592
      break;
1913
2593
 
1914
2594
    case HA_ADMIN_OK:
1915
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1916
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
2595
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2596
      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
1917
2597
      break;
1918
2598
 
1919
2599
    case HA_ADMIN_FAILED:
1920
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1921
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
2600
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2601
      protocol->store(STRING_WITH_LEN("Operation failed"),
 
2602
                      system_charset_info);
1922
2603
      break;
1923
2604
 
1924
2605
    case HA_ADMIN_REJECT:
1925
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1926
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
2606
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2607
      protocol->store(STRING_WITH_LEN("Operation need committed state"),
 
2608
                      system_charset_info);
1927
2609
      open_for_modify= false;
1928
2610
      break;
1929
2611
 
1930
2612
    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"));
 
2613
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
2614
      protocol->store(STRING_WITH_LEN("Table is already up to date"),
 
2615
                      system_charset_info);
1933
2616
      break;
1934
2617
 
1935
2618
    case HA_ADMIN_CORRUPT:
1936
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1937
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
2619
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2620
      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
1938
2621
      fatal_error=1;
1939
2622
      break;
1940
2623
 
1941
2624
    case HA_ADMIN_INVALID:
1942
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1943
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1944
 
      break;
 
2625
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2626
      protocol->store(STRING_WITH_LEN("Invalid argument"),
 
2627
                      system_charset_info);
 
2628
      break;
 
2629
 
 
2630
    case HA_ADMIN_TRY_ALTER:
 
2631
    {
 
2632
      /*
 
2633
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2634
        "try with alter", so here we close the table, do an ALTER Table,
 
2635
        reopen the table and do ha_innobase::analyze() on it.
 
2636
      */
 
2637
      ha_autocommit_or_rollback(thd, 0);
 
2638
      close_thread_tables(thd);
 
2639
      TableList *save_next_local= table->next_local,
 
2640
                 *save_next_global= table->next_global;
 
2641
      table->next_local= table->next_global= 0;
 
2642
      tmp_disable_binlog(thd); // binlogging is done by caller if wanted
 
2643
      result_code= mysql_recreate_table(thd, table);
 
2644
      reenable_binlog(thd);
 
2645
      /*
 
2646
        mysql_recreate_table() can push OK or ERROR.
 
2647
        Clear 'OK' status. If there is an error, keep it:
 
2648
        we will store the error message in a result set row 
 
2649
        and then clear.
 
2650
      */
 
2651
      if (thd->main_da.is_ok())
 
2652
        thd->main_da.reset_diagnostics_area();
 
2653
      ha_autocommit_or_rollback(thd, 0);
 
2654
      close_thread_tables(thd);
 
2655
      if (!result_code) // recreation went ok
 
2656
      {
 
2657
        if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
 
2658
            ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
 
2659
          result_code= 0; // analyze went ok
 
2660
      }
 
2661
      if (result_code) // either mysql_recreate_table or analyze failed
 
2662
      {
 
2663
        assert(thd->is_error());
 
2664
        if (thd->is_error())
 
2665
        {
 
2666
          const char *err_msg= thd->main_da.message();
 
2667
          if (!thd->vio_ok())
 
2668
          {
 
2669
            sql_print_error(err_msg);
 
2670
          }
 
2671
          else
 
2672
          {
 
2673
            /* Hijack the row already in-progress. */
 
2674
            protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2675
            protocol->store(err_msg, system_charset_info);
 
2676
            (void)protocol->write();
 
2677
            /* Start off another row for HA_ADMIN_FAILED */
 
2678
            protocol->prepare_for_resend();
 
2679
            protocol->store(table_name, system_charset_info);
 
2680
            protocol->store(operator_name, system_charset_info);
 
2681
          }
 
2682
          thd->clear_error();
 
2683
        }
 
2684
      }
 
2685
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2686
      table->next_local= save_next_local;
 
2687
      table->next_global= save_next_global;
 
2688
      goto send_result_message;
 
2689
    }
 
2690
    case HA_ADMIN_WRONG_CHECKSUM:
 
2691
    {
 
2692
      protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
2693
      protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
 
2694
                      system_charset_info);
 
2695
      break;
 
2696
    }
 
2697
 
 
2698
    case HA_ADMIN_NEEDS_UPGRADE:
 
2699
    case HA_ADMIN_NEEDS_ALTER:
 
2700
    {
 
2701
      char buf[ERRMSGSIZE];
 
2702
      uint32_t length;
 
2703
 
 
2704
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2705
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2706
      protocol->store(buf, length, system_charset_info);
 
2707
      fatal_error=1;
 
2708
      break;
 
2709
    }
1945
2710
 
1946
2711
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1947
2712
      {
1949
2714
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1950
2715
                             _("Unknown - internal error %d during operation"),
1951
2716
                             result_code);
1952
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1953
 
        session->getClient()->store(buf, length);
 
2717
        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2718
        protocol->store(buf, length, system_charset_info);
1954
2719
        fatal_error=1;
1955
2720
        break;
1956
2721
      }
1958
2723
    if (table->table)
1959
2724
    {
1960
2725
      if (fatal_error)
1961
 
      {
1962
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1963
 
      }
 
2726
        table->table->s->version=0;               // Force close of table
1964
2727
      else if (open_for_modify)
1965
2728
      {
1966
 
        if (table->table->getShare()->getType())
1967
 
        {
1968
 
          table->table->cursor->info(HA_STATUS_CONST);
1969
 
        }
 
2729
        if (table->table->s->tmp_table)
 
2730
          table->table->file->info(HA_STATUS_CONST);
1970
2731
        else
1971
2732
        {
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);
 
2733
          pthread_mutex_lock(&LOCK_open);
 
2734
          remove_table_from_cache(thd, table->table->s->db.str,
 
2735
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2736
          pthread_mutex_unlock(&LOCK_open);
1975
2737
        }
1976
2738
      }
1977
2739
    }
1978
 
    transaction_services.autocommitOrRollback(*session, false);
1979
 
    session->endTransaction(COMMIT);
1980
 
    session->close_thread_tables();
 
2740
    ha_autocommit_or_rollback(thd, 0);
 
2741
    end_trans(thd, COMMIT);
 
2742
    close_thread_tables(thd);
1981
2743
    table->table=0;                             // For query cache
1982
 
    if (session->getClient()->flush())
 
2744
    if (protocol->write())
1983
2745
      goto err;
1984
2746
  }
1985
2747
 
1986
 
  session->my_eof();
 
2748
  my_eof(thd);
1987
2749
  return(false);
1988
2750
 
1989
2751
err:
1990
 
  transaction_services.autocommitOrRollback(*session, true);
1991
 
  session->endTransaction(ROLLBACK);
1992
 
  session->close_thread_tables();                       // Shouldn't be needed
 
2752
  ha_autocommit_or_rollback(thd, 1);
 
2753
  end_trans(thd, ROLLBACK);
 
2754
  close_thread_tables(thd);                     // Shouldn't be needed
1993
2755
  if (table)
1994
2756
    table->table=0;
1995
2757
  return(true);
1996
2758
}
1997
2759
 
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
 
}
 
2760
 
 
2761
bool mysql_repair_table(THD* thd, TableList* tables, HA_CHECK_OPT* check_opt)
 
2762
{
 
2763
  return(mysql_admin_table(thd, tables, check_opt,
 
2764
                                "repair", TL_WRITE, 1,
 
2765
                                test(check_opt->sql_flags & TT_USEFRM),
 
2766
                                HA_OPEN_FOR_REPAIR,
 
2767
                                &prepare_for_repair,
 
2768
                                &handler::ha_repair));
 
2769
}
 
2770
 
 
2771
 
 
2772
bool mysql_optimize_table(THD* thd, TableList* tables, HA_CHECK_OPT* check_opt)
 
2773
{
 
2774
  return(mysql_admin_table(thd, tables, check_opt,
 
2775
                                "optimize", TL_WRITE, 1,0,0,0,
 
2776
                                &handler::ha_optimize));
 
2777
}
 
2778
 
 
2779
 
 
2780
/*
 
2781
  Assigned specified indexes for a table into key cache
 
2782
 
 
2783
  SYNOPSIS
 
2784
    mysql_assign_to_keycache()
 
2785
    thd         Thread object
 
2786
    tables      Table list (one table only)
 
2787
 
 
2788
  RETURN VALUES
 
2789
   false ok
 
2790
   true  error
 
2791
*/
 
2792
 
 
2793
bool mysql_assign_to_keycache(THD* thd, TableList* tables,
 
2794
                             LEX_STRING *key_cache_name)
 
2795
{
 
2796
  HA_CHECK_OPT check_opt;
 
2797
  KEY_CACHE *key_cache;
 
2798
 
 
2799
  check_opt.init();
 
2800
  pthread_mutex_lock(&LOCK_global_system_variables);
 
2801
  if (!(key_cache= get_key_cache(key_cache_name)))
 
2802
  {
 
2803
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2804
    my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
 
2805
    return(true);
 
2806
  }
 
2807
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
2808
  check_opt.key_cache= key_cache;
 
2809
  return(mysql_admin_table(thd, tables, &check_opt,
 
2810
                                "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
 
2811
                                0, 0, &handler::assign_to_keycache));
 
2812
}
 
2813
 
 
2814
 
 
2815
/*
 
2816
  Reassign all tables assigned to a key cache to another key cache
 
2817
 
 
2818
  SYNOPSIS
 
2819
    reassign_keycache_tables()
 
2820
    thd         Thread object
 
2821
    src_cache   Reference to the key cache to clean up
 
2822
    dest_cache  New key cache
 
2823
 
 
2824
  NOTES
 
2825
    This is called when one sets a key cache size to zero, in which
 
2826
    case we have to move the tables associated to this key cache to
 
2827
    the "default" one.
 
2828
 
 
2829
    One has to ensure that one never calls this function while
 
2830
    some other thread is changing the key cache. This is assured by
 
2831
    the caller setting src_cache->in_init before calling this function.
 
2832
 
 
2833
    We don't delete the old key cache as there may still be pointers pointing
 
2834
    to it for a while after this function returns.
 
2835
 
 
2836
 RETURN VALUES
 
2837
    0     ok
 
2838
*/
 
2839
 
 
2840
int reassign_keycache_tables(THD *thd __attribute__((unused)),
 
2841
                             KEY_CACHE *src_cache,
 
2842
                             KEY_CACHE *dst_cache)
 
2843
{
 
2844
  assert(src_cache != dst_cache);
 
2845
  assert(src_cache->in_init);
 
2846
  src_cache->param_buff_size= 0;                // Free key cache
 
2847
  ha_resize_key_cache(src_cache);
 
2848
  ha_change_key_cache(src_cache, dst_cache);
 
2849
  return(0);
 
2850
}
 
2851
 
 
2852
/**
 
2853
  @brief          Create frm file based on I_S table
 
2854
 
 
2855
  @param[in]      thd                      thread handler
 
2856
  @param[in]      schema_table             I_S table           
 
2857
  @param[in]      dst_path                 path where frm should be created
 
2858
  @param[in]      create_info              Create info
 
2859
 
 
2860
  @return         Operation status
 
2861
    @retval       0                        success
 
2862
    @retval       1                        error
 
2863
*/
 
2864
bool mysql_create_like_schema_frm(THD* thd, TableList* schema_table,
 
2865
                                  char *dst_path, HA_CREATE_INFO *create_info)
 
2866
{
 
2867
  HA_CREATE_INFO local_create_info;
 
2868
  Alter_info alter_info;
 
2869
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
2870
  uint32_t keys= schema_table->table->s->keys;
 
2871
  uint32_t db_options= 0;
 
2872
 
 
2873
  memset(&local_create_info, 0, sizeof(local_create_info));
 
2874
  local_create_info.db_type= schema_table->table->s->db_type();
 
2875
  local_create_info.row_type= schema_table->table->s->row_type;
 
2876
  local_create_info.default_table_charset=default_charset_info;
 
2877
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
2878
  schema_table->table->use_all_columns();
 
2879
  if (mysql_prepare_alter_table(thd, schema_table->table,
 
2880
                                &local_create_info, &alter_info))
 
2881
    return(1);
 
2882
  if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
 
2883
                                 tmp_table, &db_options,
 
2884
                                 schema_table->table->file,
 
2885
                                 &schema_table->table->s->key_info, &keys, 0))
 
2886
    return(1);
 
2887
  local_create_info.max_rows= 0;
 
2888
  if (mysql_create_frm(thd, dst_path, NULL, NULL,
 
2889
                       &local_create_info, alter_info.create_list,
 
2890
                       keys, schema_table->table->s->key_info,
 
2891
                       schema_table->table->file))
 
2892
    return(1);
 
2893
  return(0);
 
2894
}
 
2895
 
2087
2896
 
2088
2897
/*
2089
2898
  Create a table identical to the specified table
2090
2899
 
2091
2900
  SYNOPSIS
2092
 
    create_like_table()
2093
 
    session             Thread object
 
2901
    mysql_create_like_table()
 
2902
    thd         Thread object
2094
2903
    table       Table list element for target table
2095
2904
    src_table   Table list element for source table
2096
2905
    create_info Create info
2100
2909
    true  error
2101
2910
*/
2102
2911
 
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)
 
2912
bool mysql_create_like_table(THD* thd, TableList* table, TableList* src_table,
 
2913
                             HA_CREATE_INFO *create_info)
2109
2914
{
 
2915
  Table *name_lock= 0;
 
2916
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2917
  uint32_t dst_path_length;
 
2918
  char *db= table->db;
 
2919
  char *table_name= table->table_name;
 
2920
  int  err;
2110
2921
  bool res= true;
2111
 
  bool table_exists= false;
 
2922
  uint32_t not_used;
2112
2923
 
2113
2924
  /*
 
2925
    By opening source table we guarantee that it exists and no concurrent
 
2926
    DDL operation will mess with it. Later we also take an exclusive
 
2927
    name-lock on target table name, which makes copying of .frm file,
 
2928
    call to ha_create_table() and binlogging atomic against concurrent DML
 
2929
    and DDL operations on target table. Thus by holding both these "locks"
 
2930
    we ensure that our statement is properly isolated from all concurrent
 
2931
    operations which matter.
 
2932
  */
 
2933
  if (open_tables(thd, &src_table, &not_used, 0))
 
2934
    return(true);
 
2935
 
 
2936
  strxmov(src_path, src_table->table->s->path.str, reg_ext, NULL);
 
2937
 
 
2938
  /* 
2114
2939
    Check that destination tables does not exist. Note that its name
2115
2940
    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
 
 
 
2941
  */
 
2942
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2943
  {
 
2944
    if (find_temporary_table(thd, db, table_name))
 
2945
      goto table_exists;
 
2946
    dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
 
2947
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
 
2948
  }
 
2949
  else
 
2950
  {
 
2951
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
2952
      goto err;
 
2953
    if (!name_lock)
 
2954
      goto table_exists;
 
2955
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2956
                                          db, table_name, reg_ext, 0);
 
2957
    if (!access(dst_path, F_OK))
 
2958
      goto table_exists;
 
2959
  }
 
2960
 
 
2961
  /*
 
2962
    Create a new table by copying from source table
 
2963
 
 
2964
    Altough exclusive name-lock on target table protects us from concurrent
 
2965
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2966
    to ha_create_table() in critical section protected by LOCK_open in order
 
2967
    to provide minimal atomicity against operations which disregard name-locks,
 
2968
    like I_S implementation, for example. This is a temporary and should not
 
2969
    be copied. Instead we should fix our code to always honor name-locks.
 
2970
 
 
2971
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2972
    during the call to ha_create_table(). See bug #28614 for more info.
 
2973
  */
 
2974
  pthread_mutex_lock(&LOCK_open);
 
2975
  if (src_table->schema_table)
 
2976
  {
 
2977
    if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
 
2978
    {
 
2979
      pthread_mutex_unlock(&LOCK_open);
 
2980
      goto err;
 
2981
    }
 
2982
  }
 
2983
  else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
 
2984
  {
 
2985
    if (my_errno == ENOENT)
 
2986
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2987
    else
 
2988
      my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2989
    pthread_mutex_unlock(&LOCK_open);
 
2990
    goto err;
 
2991
  }
 
2992
 
 
2993
  /*
 
2994
    As mysql_truncate don't work on a new table at this stage of
 
2995
    creation, instead create the table directly (for both normal
 
2996
    and temporary tables).
 
2997
  */
 
2998
  dst_path[dst_path_length - reg_ext_length]= '\0';  // Remove .frm
 
2999
  if (thd->variables.keep_files_on_create)
 
3000
    create_info->options|= HA_CREATE_KEEP_FILES;
 
3001
  err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
 
3002
  pthread_mutex_unlock(&LOCK_open);
 
3003
 
 
3004
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
3005
  {
 
3006
    if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
 
3007
                                     OTM_OPEN))
 
3008
    {
 
3009
      (void) rm_temporary_table(create_info->db_type,
 
3010
                                dst_path, false); /* purecov: inspected */
 
3011
      goto err;     /* purecov: inspected */
 
3012
    }
 
3013
  }
 
3014
  else if (err)
 
3015
  {
 
3016
    (void) quick_rm_table(create_info->db_type, db,
 
3017
                          table_name, 0); /* purecov: inspected */
 
3018
    goto err;       /* purecov: inspected */
 
3019
  }
 
3020
 
 
3021
  /*
 
3022
    We have to write the query before we unlock the tables.
 
3023
  */
 
3024
  if (thd->current_stmt_binlog_row_based)
 
3025
  {
 
3026
    /*
 
3027
       Since temporary tables are not replicated under row-based
 
3028
       replication, CREATE TABLE ... LIKE ... needs special
 
3029
       treatement.  We have four cases to consider, according to the
 
3030
       following decision table:
 
3031
 
 
3032
           ==== ========= ========= ==============================
 
3033
           Case    Target    Source Write to binary log
 
3034
           ==== ========= ========= ==============================
 
3035
           1       normal    normal Original statement
 
3036
           2       normal temporary Generated statement
 
3037
           3    temporary    normal Nothing
 
3038
           4    temporary temporary Nothing
 
3039
           ==== ========= ========= ==============================
 
3040
    */
 
3041
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
3042
    {
 
3043
      if (src_table->table->s->tmp_table)               // Case 2
 
3044
      {
 
3045
        char buf[2048];
 
3046
        String query(buf, sizeof(buf), system_charset_info);
 
3047
        query.length(0);  // Have to zero it since constructor doesn't
 
3048
 
 
3049
 
 
3050
        /*
 
3051
          Here we open the destination table, on which we already have
 
3052
          name-lock. This is needed for store_create_info() to work.
 
3053
          The table will be closed by unlink_open_table() at the end
 
3054
          of this function.
 
3055
        */
 
3056
        table->table= name_lock;
 
3057
        pthread_mutex_lock(&LOCK_open);
 
3058
        if (reopen_name_locked_table(thd, table, false))
 
3059
        {
 
3060
          pthread_mutex_unlock(&LOCK_open);
 
3061
          goto err;
 
3062
        }
 
3063
        pthread_mutex_unlock(&LOCK_open);
 
3064
 
 
3065
        int result= store_create_info(thd, table, &query,
 
3066
                                               create_info);
 
3067
 
 
3068
        assert(result == 0); // store_create_info() always return 0
 
3069
        write_bin_log(thd, true, query.ptr(), query.length());
 
3070
      }
 
3071
      else                                      // Case 1
 
3072
        write_bin_log(thd, true, thd->query, thd->query_length);
 
3073
    }
 
3074
    /*
 
3075
      Case 3 and 4 does nothing under RBR
 
3076
    */
 
3077
  }
 
3078
  else
 
3079
    write_bin_log(thd, true, thd->query, thd->query_length);
 
3080
 
 
3081
  res= false;
 
3082
  goto err;
 
3083
 
 
3084
table_exists:
 
3085
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
3086
  {
 
3087
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
3088
    snprintf(warn_buff, sizeof(warn_buff),
 
3089
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
3090
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3091
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
3092
    res= false;
 
3093
  }
 
3094
  else
 
3095
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
3096
 
 
3097
err:
 
3098
  if (name_lock)
 
3099
  {
 
3100
    pthread_mutex_lock(&LOCK_open);
 
3101
    unlink_open_table(thd, name_lock, false);
 
3102
    pthread_mutex_unlock(&LOCK_open);
 
3103
  }
 
3104
  return(res);
 
3105
}
 
3106
 
 
3107
 
 
3108
bool mysql_analyze_table(THD* thd, TableList* tables, HA_CHECK_OPT* check_opt)
 
3109
{
 
3110
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
3111
 
 
3112
  return(mysql_admin_table(thd, tables, check_opt,
 
3113
                                "analyze", lock_type, 1, 0, 0, 0,
 
3114
                                &handler::ha_analyze));
 
3115
}
 
3116
 
 
3117
 
 
3118
bool mysql_check_table(THD* thd, TableList* tables,HA_CHECK_OPT* check_opt)
 
3119
{
 
3120
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
3121
 
 
3122
  return(mysql_admin_table(thd, tables, check_opt,
 
3123
                                "check", lock_type,
 
3124
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
3125
                                &handler::ha_check));
 
3126
}
 
3127
 
 
3128
 
 
3129
/* table_list should contain just one table */
 
3130
static int
 
3131
mysql_discard_or_import_tablespace(THD *thd,
 
3132
                                   TableList *table_list,
 
3133
                                   enum tablespace_op_type tablespace_op)
 
3134
{
 
3135
  Table *table;
 
3136
  bool discard;
 
3137
  int error;
 
3138
 
 
3139
  /*
 
3140
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
 
3141
    ALTER Table
 
3142
  */
 
3143
 
 
3144
  thd->set_proc_info("discard_or_import_tablespace");
 
3145
 
 
3146
  discard= test(tablespace_op == DISCARD_TABLESPACE);
 
3147
 
 
3148
 /*
 
3149
   We set this flag so that ha_innobase::open and ::external_lock() do
 
3150
   not complain when we lock the table
 
3151
 */
 
3152
  thd->tablespace_op= true;
 
3153
  if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
 
3154
  {
 
3155
    thd->tablespace_op=false;
 
3156
    return(-1);
 
3157
  }
 
3158
 
 
3159
  error= table->file->ha_discard_or_import_tablespace(discard);
 
3160
 
 
3161
  thd->set_proc_info("end");
 
3162
 
 
3163
  if (error)
 
3164
    goto err;
 
3165
 
 
3166
  /* The ALTER Table is always in its own transaction */
 
3167
  error = ha_autocommit_or_rollback(thd, 0);
 
3168
  if (end_active_trans(thd))
 
3169
    error=1;
 
3170
  if (error)
 
3171
    goto err;
 
3172
  write_bin_log(thd, false, thd->query, thd->query_length);
 
3173
 
 
3174
err:
 
3175
  ha_autocommit_or_rollback(thd, error);
 
3176
  thd->tablespace_op=false;
 
3177
  
 
3178
  if (error == 0)
 
3179
  {
 
3180
    my_ok(thd);
 
3181
    return(0);
 
3182
  }
 
3183
 
 
3184
  table->file->print_error(error, MYF(0));
 
3185
    
 
3186
  return(-1);
 
3187
}
 
3188
 
 
3189
/**
 
3190
  Copy all changes detected by parser to the HA_ALTER_FLAGS
 
3191
*/
 
3192
 
 
3193
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
 
3194
{
 
3195
  uint32_t flags= alter_info->flags;
 
3196
 
 
3197
  if (ALTER_ADD_COLUMN & flags)
 
3198
    *alter_flags|= HA_ADD_COLUMN;
 
3199
  if (ALTER_DROP_COLUMN & flags)
 
3200
    *alter_flags|= HA_DROP_COLUMN;
 
3201
  if (ALTER_RENAME & flags)
 
3202
    *alter_flags|= HA_RENAME_TABLE;
 
3203
  if (ALTER_CHANGE_COLUMN & flags)
 
3204
    *alter_flags|= HA_CHANGE_COLUMN;
 
3205
  if (ALTER_COLUMN_DEFAULT & flags)
 
3206
    *alter_flags|= HA_COLUMN_DEFAULT_VALUE;
 
3207
  if (ALTER_COLUMN_STORAGE & flags)
 
3208
    *alter_flags|= HA_COLUMN_STORAGE;
 
3209
  if (ALTER_COLUMN_FORMAT & flags)
 
3210
    *alter_flags|= HA_COLUMN_FORMAT;
 
3211
  if (ALTER_COLUMN_ORDER & flags)
 
3212
    *alter_flags|= HA_ALTER_COLUMN_ORDER;
 
3213
  if (ALTER_STORAGE & flags)
 
3214
    *alter_flags|= HA_ALTER_STORAGE;
 
3215
  if (ALTER_ROW_FORMAT & flags)
 
3216
    *alter_flags|= HA_ALTER_ROW_FORMAT;
 
3217
  if (ALTER_RECREATE & flags)
 
3218
    *alter_flags|= HA_RECREATE;
 
3219
  if (ALTER_FOREIGN_KEY & flags)
 
3220
    *alter_flags|= HA_ALTER_FOREIGN_KEY;
 
3221
}
 
3222
 
 
3223
 
 
3224
/**
 
3225
   @param       thd                Thread
 
3226
   @param       table              The original table.
 
3227
   @param       alter_info         Alter options, fields and keys for the new
 
3228
                                   table.
 
3229
   @param       create_info        Create options for the new table.
 
3230
   @param       order_num          Number of order list elements.
 
3231
   @param[out]  ha_alter_flags  Flags that indicate what will be changed
 
3232
   @param[out]  ha_alter_info      Data structures needed for on-line alter
 
3233
   @param[out]  table_changes      Information about particular change
 
3234
 
 
3235
   First argument 'table' contains information of the original
 
3236
   table, which includes all corresponding parts that the new
 
3237
   table has in arguments create_list, key_list and create_info.
 
3238
 
 
3239
   By comparing the changes between the original and new table
 
3240
   we can determine how much it has changed after ALTER Table
 
3241
   and whether we need to make a copy of the table, or just change
 
3242
   the .frm file.
 
3243
 
 
3244
   Mark any changes detected in the ha_alter_flags.
 
3245
 
 
3246
   If there are no data changes, but index changes, 'index_drop_buffer'
 
3247
   and/or 'index_add_buffer' are populated with offsets into
 
3248
   table->key_info or key_info_buffer respectively for the indexes
 
3249
   that need to be dropped and/or (re-)created.
 
3250
 
 
3251
   @retval true  error
 
3252
   @retval false success
 
3253
*/
 
3254
 
 
3255
static
 
3256
bool
 
3257
compare_tables(THD *thd,
 
3258
               Table *table,
 
3259
               Alter_info *alter_info,
 
3260
                           HA_CREATE_INFO *create_info,
 
3261
               uint32_t order_num,
 
3262
               HA_ALTER_FLAGS *alter_flags,
 
3263
               HA_ALTER_INFO *ha_alter_info,
 
3264
               uint32_t *table_changes)
 
3265
{
 
3266
  Field **f_ptr, *field;
 
3267
  uint32_t table_changes_local= 0;
 
3268
  List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
 
3269
  Create_field *new_field;
 
3270
  KEY_PART_INFO *key_part;
 
3271
  KEY_PART_INFO *end;
 
3272
  /*
 
3273
    Remember if the new definition has new VARCHAR column;
 
3274
    create_info->varchar will be reset in mysql_prepare_create_table.
 
3275
  */
 
3276
  bool varchar= create_info->varchar;
 
3277
 
 
3278
  {
 
3279
    /*
 
3280
      Create a copy of alter_info.
 
3281
      To compare the new and old table definitions, we need to "prepare"
 
3282
      the new definition - transform it from parser output to a format
 
3283
      that describes the final table layout (all column defaults are
 
3284
      initialized, duplicate columns are removed). This is done by
 
3285
      mysql_prepare_create_table.  Unfortunately,
 
3286
      mysql_prepare_create_table performs its transformations
 
3287
      "in-place", that is, modifies the argument.  Since we would
 
3288
      like to keep compare_tables() idempotent (not altering any
 
3289
      of the arguments) we create a copy of alter_info here and
 
3290
      pass it to mysql_prepare_create_table, then use the result
 
3291
      to evaluate possibility of fast ALTER Table, and then
 
3292
      destroy the copy.
 
3293
    */
 
3294
    Alter_info tmp_alter_info(*alter_info, thd->mem_root);
 
3295
    THD *thd= table->in_use;
 
3296
    uint32_t db_options= 0; /* not used */
 
3297
    /* Create the prepared information. */
 
3298
    if (mysql_prepare_create_table(thd, create_info,
 
3299
                                   &tmp_alter_info,
 
3300
                                   (table->s->tmp_table != NO_TMP_TABLE),
 
3301
                                   &db_options,
 
3302
                                   table->file,
 
3303
                                   &ha_alter_info->key_info_buffer,
 
3304
                                   &ha_alter_info->key_count,
 
3305
                                   /* select_field_count */ 0))
 
3306
      return(true);
 
3307
    /* Allocate result buffers. */
 
3308
    if (! (ha_alter_info->index_drop_buffer=
 
3309
           (uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
 
3310
        ! (ha_alter_info->index_add_buffer=
 
3311
           (uint*) thd->alloc(sizeof(uint) *
 
3312
                              tmp_alter_info.key_list.elements)))
 
3313
      return(true);
 
3314
  }
 
3315
  /*
 
3316
    First we setup ha_alter_flags based on what was detected
 
3317
    by parser
 
3318
  */
 
3319
  setup_ha_alter_flags(alter_info, alter_flags);
 
3320
 
 
3321
 
 
3322
  /*
 
3323
    Some very basic checks. If number of fields changes, or the
 
3324
    handler, we need to run full ALTER Table. In the future
 
3325
    new fields can be added and old dropped without copy, but
 
3326
    not yet.
 
3327
 
 
3328
    Test also that engine was not given during ALTER Table, or
 
3329
    we are force to run regular alter table (copy).
 
3330
    E.g. ALTER Table tbl_name ENGINE=MyISAM.
 
3331
 
 
3332
    For the following ones we also want to run regular alter table:
 
3333
    ALTER Table tbl_name order_st BY ..
 
3334
    ALTER Table tbl_name CONVERT TO CHARACTER SET ..
 
3335
 
 
3336
    At the moment we can't handle altering temporary tables without a copy.
 
3337
    We also test if OPTIMIZE Table was given and was mapped to alter table.
 
3338
    In that case we always do full copy.
 
3339
 
 
3340
    There was a bug prior to mysql-4.0.25. Number of null fields was
 
3341
    calculated incorrectly. As a result frm and data files gets out of
 
3342
    sync after fast alter table. There is no way to determine by which
 
3343
    mysql version (in 4.0 and 4.1 branches) table was created, thus we
 
3344
    disable fast alter table for all tables created by mysql versions
 
3345
    prior to 5.0 branch.
 
3346
    See BUG#6236.
 
3347
  */
 
3348
  if (table->s->fields != alter_info->create_list.elements ||
 
3349
      table->s->db_type() != create_info->db_type ||
 
3350
      table->s->tmp_table ||
 
3351
      create_info->used_fields & HA_CREATE_USED_ENGINE ||
 
3352
      create_info->used_fields & HA_CREATE_USED_CHARSET ||
 
3353
      create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
 
3354
      create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
 
3355
      (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
 
3356
      order_num ||
 
3357
      !table->s->mysql_version ||
 
3358
      (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
 
3359
  {
 
3360
    *table_changes= IS_EQUAL_NO;
 
3361
    /*
 
3362
      Check what has changed and set alter_flags
 
3363
    */
 
3364
    if (table->s->fields < alter_info->create_list.elements)
 
3365
      *alter_flags|= HA_ADD_COLUMN;
 
3366
    else if (table->s->fields > alter_info->create_list.elements)
 
3367
      *alter_flags|= HA_DROP_COLUMN;
 
3368
    if (create_info->db_type != table->s->db_type() ||
 
3369
        create_info->used_fields & HA_CREATE_USED_ENGINE)
 
3370
      *alter_flags|= HA_ALTER_STORAGE_ENGINE;
 
3371
    if (create_info->used_fields & HA_CREATE_USED_CHARSET)
 
3372
      *alter_flags|= HA_CHANGE_CHARACTER_SET;
 
3373
    if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
 
3374
      *alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
 
3375
    if (alter_info->flags & ALTER_RECREATE)
 
3376
      *alter_flags|= HA_RECREATE;
 
3377
    /* TODO check for ADD/DROP FOREIGN KEY */
 
3378
    if (alter_info->flags & ALTER_FOREIGN_KEY)
 
3379
      *alter_flags|=  HA_ALTER_FOREIGN_KEY;
 
3380
    if (!table->s->mysql_version ||
 
3381
        (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
 
3382
      *alter_flags|=  HA_ALTER_COLUMN_TYPE;
 
3383
  }
 
3384
  /*
 
3385
    Go through fields and check if the original ones are compatible
 
3386
    with new table.
 
3387
  */
 
3388
  for (f_ptr= table->field, new_field= new_field_it++;
 
3389
       (new_field && (field= *f_ptr));
 
3390
       f_ptr++, new_field= new_field_it++)
 
3391
  {
 
3392
    /* Make sure we have at least the default charset in use. */
 
3393
    if (!new_field->charset)
 
3394
      new_field->charset= create_info->default_table_charset;
 
3395
 
 
3396
    /* Don't pack rows in old tables if the user has requested this. */
 
3397
    if (create_info->row_type == ROW_TYPE_DYNAMIC ||
 
3398
        (new_field->flags & BLOB_FLAG) ||
 
3399
        (new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
 
3400
      create_info->table_options|= HA_OPTION_PACK_RECORD;
 
3401
 
 
3402
    /* Check how fields have been modified */
 
3403
    if (alter_info->flags & ALTER_CHANGE_COLUMN)
 
3404
    {
 
3405
      /* Evaluate changes bitmap and send to check_if_incompatible_data() */
 
3406
      if (!(table_changes_local= field->is_equal(new_field)))
 
3407
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
3408
 
 
3409
      /* Check if field was renamed */
 
3410
      field->flags&= ~FIELD_IS_RENAMED;
 
3411
      if (my_strcasecmp(system_charset_info,
 
3412
                        field->field_name,
 
3413
                        new_field->field_name))
 
3414
      {
 
3415
        field->flags|= FIELD_IS_RENAMED;
 
3416
        *alter_flags|= HA_ALTER_COLUMN_NAME;
 
3417
      }
 
3418
 
 
3419
      *table_changes&= table_changes_local;
 
3420
      if (table_changes_local == IS_EQUAL_PACK_LENGTH)
 
3421
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
3422
 
 
3423
      /* Check that NULL behavior is same for old and new fields */
 
3424
      if ((new_field->flags & NOT_NULL_FLAG) !=
 
3425
          (uint) (field->flags & NOT_NULL_FLAG))
 
3426
      {
 
3427
        *table_changes= IS_EQUAL_NO;
 
3428
        *alter_flags|= HA_ALTER_COLUMN_NULLABLE;
 
3429
      }
 
3430
    }
 
3431
 
 
3432
    /* Clear indexed marker */
 
3433
    field->flags&= ~FIELD_IN_ADD_INDEX;
 
3434
  }
 
3435
 
 
3436
  /*
 
3437
    Go through keys and check if the original ones are compatible
 
3438
    with new table.
 
3439
  */
 
3440
  KEY *table_key;
 
3441
  KEY *table_key_end= table->key_info + table->s->keys;
 
3442
  KEY *new_key;
 
3443
  KEY *new_key_end=
 
3444
       ha_alter_info->key_info_buffer + ha_alter_info->key_count;
 
3445
 
 
3446
  /*
 
3447
    Step through all keys of the old table and search matching new keys.
 
3448
  */
 
3449
  ha_alter_info->index_drop_count= 0;
 
3450
  ha_alter_info->index_add_count= 0;
 
3451
  for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
3452
  {
 
3453
    KEY_PART_INFO *table_part;
 
3454
    KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
 
3455
    KEY_PART_INFO *new_part;
 
3456
 
 
3457
    /* Search a new key with the same name. */
 
3458
    for (new_key= ha_alter_info->key_info_buffer;
 
3459
         new_key < new_key_end;
 
3460
         new_key++)
 
3461
    {
 
3462
      if (! strcmp(table_key->name, new_key->name))
 
3463
        break;
 
3464
    }
 
3465
    if (new_key >= new_key_end)
 
3466
    {
 
3467
      /* Key not found. Add the offset of the key to the drop buffer. */
 
3468
      ha_alter_info->index_drop_buffer
 
3469
           [ha_alter_info->index_drop_count++]=
 
3470
           table_key - table->key_info;
 
3471
      if (table_key->flags & HA_NOSAME)
 
3472
      {
 
3473
        /* Unique key. Check for "PRIMARY". */
 
3474
        if (! my_strcasecmp(system_charset_info,
 
3475
                            table_key->name, primary_key_name))
 
3476
          *alter_flags|= HA_DROP_PK_INDEX;
 
3477
        else
 
3478
          *alter_flags|= HA_DROP_UNIQUE_INDEX;
 
3479
      }
 
3480
      else
 
3481
        *alter_flags|= HA_DROP_INDEX;
 
3482
      *table_changes= IS_EQUAL_NO;
 
3483
      continue;
 
3484
    }
 
3485
 
 
3486
    /* Check that the key types are compatible between old and new tables. */
 
3487
    if ((table_key->algorithm != new_key->algorithm) ||
 
3488
        ((table_key->flags & HA_KEYFLAG_MASK) !=
 
3489
         (new_key->flags & HA_KEYFLAG_MASK)) ||
 
3490
        (table_key->key_parts != new_key->key_parts))
 
3491
    {
 
3492
      if (table_key->flags & HA_NOSAME)
 
3493
      {
 
3494
        // Unique key. Check for "PRIMARY".
 
3495
        if (! my_strcasecmp(system_charset_info,
 
3496
                            table_key->name, primary_key_name))
 
3497
          *alter_flags|= HA_ALTER_PK_INDEX;
 
3498
        else
 
3499
          *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
3500
      }
 
3501
      else
 
3502
        *alter_flags|= HA_ALTER_INDEX;
 
3503
      goto index_changed;
 
3504
    }
 
3505
 
 
3506
    /*
 
3507
      Check that the key parts remain compatible between the old and
 
3508
      new tables.
 
3509
    */
 
3510
    for (table_part= table_key->key_part, new_part= new_key->key_part;
 
3511
         table_part < table_part_end;
 
3512
         table_part++, new_part++)
 
3513
    {
 
3514
      /*
 
3515
        Key definition has changed if we are using a different field or
 
3516
        if the used key part length is different. We know that the fields
 
3517
        did not change. Comparing field numbers is sufficient.
 
3518
      */
 
3519
      if ((table_part->length != new_part->length) ||
 
3520
          (table_part->fieldnr - 1 != new_part->fieldnr))
 
3521
      {
 
3522
        if (table_key->flags & HA_NOSAME)
 
3523
        {
 
3524
          /* Unique key. Check for "PRIMARY" */
 
3525
          if (! my_strcasecmp(system_charset_info,
 
3526
                              table_key->name, primary_key_name))
 
3527
            *alter_flags|= HA_ALTER_PK_INDEX;
 
3528
          else
 
3529
            *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
3530
        }
 
3531
        else
 
3532
          *alter_flags|= HA_ALTER_INDEX;
 
3533
        goto index_changed;
 
3534
      }
 
3535
    }
 
3536
    continue;
 
3537
 
 
3538
  index_changed:
 
3539
    /* Key modified. Add the offset of the key to both buffers. */
 
3540
    ha_alter_info->index_drop_buffer
 
3541
         [ha_alter_info->index_drop_count++]=
 
3542
         table_key - table->key_info;
 
3543
    ha_alter_info->index_add_buffer
 
3544
         [ha_alter_info->index_add_count++]=
 
3545
         new_key - ha_alter_info->key_info_buffer;
 
3546
    key_part= new_key->key_part;
 
3547
    end= key_part + new_key->key_parts;
 
3548
    for(; key_part != end; key_part++)
 
3549
    {
 
3550
      /* Mark field to be part of new key */
 
3551
      if ((field= table->field[key_part->fieldnr]))
 
3552
        field->flags|= FIELD_IN_ADD_INDEX;
 
3553
    }
 
3554
    *table_changes= IS_EQUAL_NO;
 
3555
  }
 
3556
  /*end of for (; table_key < table_key_end;) */
 
3557
 
 
3558
  /*
 
3559
    Step through all keys of the new table and find matching old keys.
 
3560
  */
 
3561
  for (new_key= ha_alter_info->key_info_buffer;
 
3562
       new_key < new_key_end;
 
3563
       new_key++)
 
3564
  {
 
3565
    /* Search an old key with the same name. */
 
3566
    for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
3567
    {
 
3568
      if (! strcmp(table_key->name, new_key->name))
 
3569
        break;
 
3570
    }
 
3571
    if (table_key >= table_key_end)
 
3572
    {
 
3573
      /* Key not found. Add the offset of the key to the add buffer. */
 
3574
      ha_alter_info->index_add_buffer
 
3575
           [ha_alter_info->index_add_count++]=
 
3576
           new_key - ha_alter_info->key_info_buffer;
 
3577
      key_part= new_key->key_part;
 
3578
      end= key_part + new_key->key_parts;
 
3579
      for(; key_part != end; key_part++)
 
3580
      {
 
3581
        /* Mark field to be part of new key */
 
3582
        if ((field= table->field[key_part->fieldnr]))
 
3583
          field->flags|= FIELD_IN_ADD_INDEX;
 
3584
      }
 
3585
      if (new_key->flags & HA_NOSAME)
 
3586
      {
 
3587
        /* Unique key. Check for "PRIMARY" */
 
3588
        if (! my_strcasecmp(system_charset_info,
 
3589
                            new_key->name, primary_key_name))
 
3590
          *alter_flags|= HA_ADD_PK_INDEX;
 
3591
        else
 
3592
        *alter_flags|= HA_ADD_UNIQUE_INDEX;
 
3593
      }
 
3594
      else
 
3595
        *alter_flags|= HA_ADD_INDEX;
 
3596
      *table_changes= IS_EQUAL_NO;
 
3597
    }
 
3598
  }
 
3599
 
 
3600
  return(false);
 
3601
}
 
3602
 
 
3603
 
 
3604
/*
 
3605
  Manages enabling/disabling of indexes for ALTER Table
 
3606
 
 
3607
  SYNOPSIS
 
3608
    alter_table_manage_keys()
 
3609
      table                  Target table
 
3610
      indexes_were_disabled  Whether the indexes of the from table
 
3611
                             were disabled
 
3612
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
 
3613
 
 
3614
  RETURN VALUES
 
3615
    false  OK
 
3616
    true   Error
 
3617
*/
 
3618
 
 
3619
static
 
3620
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
 
3621
                             enum enum_enable_or_disable keys_onoff)
 
3622
{
 
3623
  int error= 0;
 
3624
  switch (keys_onoff) {
 
3625
  case ENABLE:
 
3626
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3627
    break;
 
3628
  case LEAVE_AS_IS:
 
3629
    if (!indexes_were_disabled)
 
3630
      break;
 
3631
    /* fall-through: disabled indexes */
 
3632
  case DISABLE:
 
3633
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3634
  }
 
3635
 
 
3636
  if (error == HA_ERR_WRONG_COMMAND)
 
3637
  {
 
3638
    push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3639
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3640
                        table->s->table_name.str);
 
3641
    error= 0;
 
3642
  } else if (error)
 
3643
    table->file->print_error(error, MYF(0));
 
3644
 
 
3645
  return(error);
 
3646
}
 
3647
 
 
3648
int create_temporary_table(THD *thd,
 
3649
                           Table *table,
 
3650
                           char *new_db,
 
3651
                           char *tmp_name,
 
3652
                           HA_CREATE_INFO *create_info,
 
3653
                           Alter_info *alter_info,
 
3654
                           bool db_changed)
 
3655
{
 
3656
  int error;
 
3657
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
 
3658
  handlerton *old_db_type, *new_db_type;
 
3659
  old_db_type= table->s->db_type();
 
3660
  new_db_type= create_info->db_type;
 
3661
  /*
 
3662
    Handling of symlinked tables:
 
3663
    If no rename:
 
3664
      Create new data file and index file on the same disk as the
 
3665
      old data and index files.
 
3666
      Copy data.
 
3667
      Rename new data file over old data file and new index file over
 
3668
      old index file.
 
3669
      Symlinks are not changed.
 
3670
 
 
3671
   If rename:
 
3672
      Create new data file and index file on the same disk as the
 
3673
      old data and index files.  Create also symlinks to point at
 
3674
      the new tables.
 
3675
      Copy data.
 
3676
      At end, rename intermediate tables, and symlinks to intermediate
 
3677
      table, to final table name.
 
3678
      Remove old table and old symlinks
 
3679
 
 
3680
    If rename is made to another database:
 
3681
      Create new tables in new database.
 
3682
      Copy data.
 
3683
      Remove old table and symlinks.
 
3684
  */
 
3685
  if (db_changed)               // Ignore symlink if db changed
 
3686
  {
 
3687
    if (create_info->index_file_name)
 
3688
    {
 
3689
      /* Fix index_file_name to have 'tmp_name' as basename */
 
3690
      my_stpcpy(index_file, tmp_name);
 
3691
      create_info->index_file_name=fn_same(index_file,
 
3692
                                           create_info->index_file_name,
 
3693
                                           1);
 
3694
    }
 
3695
    if (create_info->data_file_name)
 
3696
    {
 
3697
      /* Fix data_file_name to have 'tmp_name' as basename */
 
3698
      my_stpcpy(data_file, tmp_name);
 
3699
      create_info->data_file_name=fn_same(data_file,
 
3700
                                          create_info->data_file_name,
 
3701
                                          1);
 
3702
    }
 
3703
  }
 
3704
  else
 
3705
    create_info->data_file_name=create_info->index_file_name=0;
 
3706
 
 
3707
  /*
 
3708
    Create a table with a temporary name.
 
3709
    With create_info->frm_only == 1 this creates a .frm file only.
 
3710
    We don't log the statement, it will be logged later.
 
3711
  */
 
3712
  tmp_disable_binlog(thd);
 
3713
  error= mysql_create_table(thd, new_db, tmp_name,
 
3714
                            create_info, alter_info, 1, 0);
 
3715
  reenable_binlog(thd);
 
3716
 
 
3717
  return(error);
 
3718
}
 
3719
 
 
3720
/*
 
3721
  Create a temporary table that reflects what an alter table operation
 
3722
  will accomplish.
 
3723
 
 
3724
  SYNOPSIS
 
3725
    create_altered_table()
 
3726
      thd              Thread handle
 
3727
      table            The original table
 
3728
      create_info      Information from the parsing phase about new
 
3729
                       table properties.
 
3730
      alter_info       Lists of fields, keys to be changed, added
 
3731
                       or dropped.
 
3732
      db_change        Specifies if the table is moved to another database
 
3733
  RETURN
 
3734
    A temporary table with all changes
 
3735
    NULL if error
 
3736
  NOTES
 
3737
    The temporary table is created without storing it in any storage engine
 
3738
    and is opened only to get the table struct and frm file reference.
 
3739
*/
 
3740
Table *create_altered_table(THD *thd,
 
3741
                            Table *table,
 
3742
                            char *new_db,
 
3743
                            HA_CREATE_INFO *create_info,
 
3744
                            Alter_info *alter_info,
 
3745
                            bool db_change)
 
3746
{
 
3747
  int error;
 
3748
  HA_CREATE_INFO altered_create_info(*create_info);
 
3749
  Table *altered_table;
 
3750
  char tmp_name[80];
 
3751
  char path[FN_REFLEN];
 
3752
 
 
3753
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
 
3754
           tmp_file_prefix, current_pid, thd->thread_id);
 
3755
  /* Safety fix for InnoDB */
 
3756
  if (lower_case_table_names)
 
3757
    my_casedn_str(files_charset_info, tmp_name);
 
3758
  altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
 
3759
  altered_create_info.frm_only= 1;
 
3760
  if ((error= create_temporary_table(thd, table, new_db, tmp_name,
 
3761
                                     &altered_create_info,
 
3762
                                     alter_info, db_change)))
 
3763
  {
 
3764
    return(NULL);
 
3765
  };
 
3766
 
 
3767
  build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
3768
                       FN_IS_TMP);
 
3769
  altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
 
3770
                                      OTM_ALTER);
 
3771
  return(altered_table);
 
3772
 
 
3773
  return(NULL);
 
3774
}
 
3775
 
 
3776
 
 
3777
/*
 
3778
  Perform a fast or on-line alter table
 
3779
 
 
3780
  SYNOPSIS
 
3781
    mysql_fast_or_online_alter_table()
 
3782
      thd              Thread handle
 
3783
      table            The original table
 
3784
      altered_table    A temporary table showing how we will change table
 
3785
      create_info      Information from the parsing phase about new
 
3786
                       table properties.
 
3787
      alter_info       Storage place for data used during different phases
 
3788
      ha_alter_flags   Bitmask that shows what will be changed
 
3789
      keys_onoff       Specifies if keys are to be enabled/disabled
 
3790
  RETURN
 
3791
     0  OK
 
3792
    >0  An error occured during the on-line alter table operation
 
3793
    -1  Error when re-opening table
 
3794
  NOTES
 
3795
    If mysql_alter_table does not need to copy the table, it is
 
3796
    either a fast alter table where the storage engine does not
 
3797
    need to know about the change, only the frm will change,
 
3798
    or the storage engine supports performing the alter table
 
3799
    operation directly, on-line without mysql having to copy
 
3800
    the table.
 
3801
*/
 
3802
int mysql_fast_or_online_alter_table(THD *thd,
 
3803
                                     Table *table,
 
3804
                                     Table *altered_table,
 
3805
                                     HA_CREATE_INFO *create_info,
 
3806
                                     HA_ALTER_INFO *alter_info,
 
3807
                                     HA_ALTER_FLAGS *ha_alter_flags,
 
3808
                                     enum enum_enable_or_disable keys_onoff)
 
3809
{
 
3810
  int error= 0;
 
3811
  bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
 
3812
  Table *t_table;
 
3813
 
 
3814
  if (online)
 
3815
  {
 
3816
   /*
 
3817
      Tell the handler to prepare for the online alter
 
3818
    */
 
3819
    if ((error= table->file->alter_table_phase1(thd,
 
3820
                                                altered_table,
 
3821
                                                create_info,
 
3822
                                                alter_info,
 
3823
                                                ha_alter_flags)))
 
3824
    {
 
3825
      goto err;
 
3826
    }
 
3827
 
 
3828
    /*
 
3829
       Tell the storage engine to perform the online alter table
 
3830
       TODO: 
 
3831
       if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
 
3832
       we need to wrap the next call with a DDL lock.
 
3833
     */
 
3834
    if ((error= table->file->alter_table_phase2(thd,
 
3835
                                                altered_table,
 
3836
                                                create_info,
 
3837
                                                alter_info,
 
3838
                                                ha_alter_flags)))
 
3839
    {
 
3840
      goto err;
 
3841
    }
 
3842
  }
 
3843
  /*
 
3844
    The final .frm file is already created as a temporary file
 
3845
    and will be renamed to the original table name.
 
3846
  */
 
3847
  pthread_mutex_lock(&LOCK_open);
 
3848
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
3849
  alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
3850
                          keys_onoff);
 
3851
  close_data_files_and_morph_locks(thd,
 
3852
                                   table->pos_in_table_list->db,
 
3853
                                   table->pos_in_table_list->table_name);
 
3854
  if (mysql_rename_table(NULL,
 
3855
                         altered_table->s->db.str,
 
3856
                         altered_table->s->table_name.str,
 
3857
                         table->s->db.str,
 
3858
                         table->s->table_name.str, FN_FROM_IS_TMP))
 
3859
  {
 
3860
    error= 1;
 
3861
    pthread_mutex_unlock(&LOCK_open);
 
3862
    goto err;
 
3863
  }
 
3864
  broadcast_refresh();
 
3865
  pthread_mutex_unlock(&LOCK_open);
 
3866
 
 
3867
  /*
 
3868
    The ALTER Table is always in its own transaction.
 
3869
    Commit must not be called while LOCK_open is locked. It could call
 
3870
    wait_if_global_read_lock(), which could create a deadlock if called
 
3871
    with LOCK_open.
 
3872
  */
 
3873
  error= ha_autocommit_or_rollback(thd, 0);
 
3874
 
 
3875
  if (ha_commit(thd))
 
3876
    error=1;
 
3877
  if (error)
 
3878
    goto err;
 
3879
  if (online)
 
3880
  {
 
3881
    pthread_mutex_lock(&LOCK_open);
 
3882
    if (reopen_table(table))
 
3883
    {
 
3884
      error= -1;
 
3885
      goto err;
 
3886
    }
 
3887
    pthread_mutex_unlock(&LOCK_open);
 
3888
    t_table= table;
 
3889
 
 
3890
   /*
 
3891
      Tell the handler that the changed frm is on disk and table
 
3892
      has been re-opened
 
3893
   */
 
3894
    if ((error= t_table->file->alter_table_phase3(thd, t_table)))
 
3895
    {
 
3896
      goto err;
 
3897
    }
 
3898
 
 
3899
    /*
 
3900
      We are going to reopen table down on the road, so we have to restore
 
3901
      state of the Table object which we used for obtaining of handler
 
3902
      object to make it suitable for reopening.
 
3903
    */
 
3904
    assert(t_table == table);
 
3905
    table->open_placeholder= 1;
 
3906
    pthread_mutex_lock(&LOCK_open);
 
3907
    close_handle_and_leave_table_as_lock(table);
 
3908
    pthread_mutex_unlock(&LOCK_open);
 
3909
  }
 
3910
 
 
3911
 err:
 
3912
  if (error)
 
3913
    return(error);
 
3914
  return 0;
 
3915
}
 
3916
 
 
3917
 
 
3918
/**
 
3919
  Prepare column and key definitions for CREATE TABLE in ALTER Table.
 
3920
 
 
3921
  This function transforms parse output of ALTER Table - lists of
 
3922
  columns and keys to add, drop or modify into, essentially,
 
3923
  CREATE TABLE definition - a list of columns and keys of the new
 
3924
  table. While doing so, it also performs some (bug not all)
 
3925
  semantic checks.
 
3926
 
 
3927
  This function is invoked when we know that we're going to
 
3928
  perform ALTER Table via a temporary table -- i.e. fast ALTER Table
 
3929
  is not possible, perhaps because the ALTER statement contains
 
3930
  instructions that require change in table data, not only in
 
3931
  table definition or indexes.
 
3932
 
 
3933
  @param[in,out]  thd         thread handle. Used as a memory pool
 
3934
                              and source of environment information.
 
3935
  @param[in]      table       the source table, open and locked
 
3936
                              Used as an interface to the storage engine
 
3937
                              to acquire additional information about
 
3938
                              the original table.
 
3939
  @param[in,out]  create_info A blob with CREATE/ALTER Table
 
3940
                              parameters
 
3941
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
 
3942
                              Originally create_info was used only in
 
3943
                              CREATE TABLE and alter_info only in ALTER Table.
 
3944
                              But since ALTER might end-up doing CREATE,
 
3945
                              this distinction is gone and we just carry
 
3946
                              around two structures.
 
3947
 
 
3948
  @return
 
3949
    Fills various create_info members based on information retrieved
 
3950
    from the storage engine.
 
3951
    Sets create_info->varchar if the table has a VARCHAR column.
 
3952
    Prepares alter_info->create_list and alter_info->key_list with
 
3953
    columns and keys of the new table.
 
3954
  @retval true   error, out of memory or a semantical error in ALTER
 
3955
                 Table instructions
 
3956
  @retval false  success
 
3957
*/
 
3958
 
 
3959
static bool
 
3960
mysql_prepare_alter_table(THD *thd, Table *table,
 
3961
                          HA_CREATE_INFO *create_info,
 
3962
                          Alter_info *alter_info)
 
3963
{
 
3964
  /* New column definitions are added here */
 
3965
  List<Create_field> new_create_list;
 
3966
  /* New key definitions are added here */
 
3967
  List<Key> new_key_list;
 
3968
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
 
3969
  List_iterator<Create_field> def_it(alter_info->create_list);
 
3970
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
 
3971
  List_iterator<Key> key_it(alter_info->key_list);
 
3972
  List_iterator<Create_field> find_it(new_create_list);
 
3973
  List_iterator<Create_field> field_it(new_create_list);
 
3974
  List<Key_part_spec> key_parts;
 
3975
  uint32_t db_create_options= (table->s->db_create_options
 
3976
                           & ~(HA_OPTION_PACK_RECORD));
 
3977
  uint32_t used_fields= create_info->used_fields;
 
3978
  KEY *key_info=table->key_info;
 
3979
  bool rc= true;
 
3980
 
 
3981
 
 
3982
  create_info->varchar= false;
 
3983
  /* Let new create options override the old ones */
 
3984
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
 
3985
    create_info->min_rows= table->s->min_rows;
 
3986
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
 
3987
    create_info->max_rows= table->s->max_rows;
 
3988
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
 
3989
    create_info->avg_row_length= table->s->avg_row_length;
 
3990
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
3991
    create_info->block_size= table->s->block_size;
 
3992
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
3993
    create_info->default_table_charset= table->s->table_charset;
 
3994
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
3995
    {
 
3996
    /* Table has an autoincrement, copy value to new table */
 
3997
    table->file->info(HA_STATUS_AUTO);
 
3998
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
 
3999
  }
 
4000
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
4001
    create_info->key_block_size= table->s->key_block_size;
 
4002
 
 
4003
  restore_record(table, s->default_values);     // Empty record for DEFAULT
 
4004
  Create_field *def;
 
4005
 
 
4006
    /*
 
4007
    First collect all fields from table which isn't in drop_list
 
4008
    */
 
4009
  Field **f_ptr,*field;
 
4010
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
 
4011
    {
 
4012
    /* Check if field should be dropped */
 
4013
    Alter_drop *drop;
 
4014
    drop_it.rewind();
 
4015
    while ((drop=drop_it++))
 
4016
    {
 
4017
      if (drop->type == Alter_drop::COLUMN &&
 
4018
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
 
4019
    {
 
4020
        /* Reset auto_increment value if it was dropped */
 
4021
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
4022
            !(used_fields & HA_CREATE_USED_AUTO))
 
4023
      {
 
4024
          create_info->auto_increment_value=0;
 
4025
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
4026
      }
 
4027
        break;
 
4028
    }
 
4029
  }
 
4030
    if (drop)
 
4031
      {
 
4032
      drop_it.remove();
 
4033
      continue;
 
4034
    }
 
4035
    /* Check if field is changed */
 
4036
    def_it.rewind();
 
4037
    while ((def=def_it++))
 
4038
    {
 
4039
      if (def->change &&
 
4040
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
4041
        break;
 
4042
    }
 
4043
    if (def)
 
4044
    {                                           // Field is changed
 
4045
      def->field=field;
 
4046
      if (!def->after)
 
4047
        {
 
4048
        new_create_list.push_back(def);
 
4049
        def_it.remove();
 
4050
        }
 
4051
      }
 
4052
      else
 
4053
      {
 
4054
      /*
 
4055
        This field was not dropped and not changed, add it to the list
 
4056
        for the new table.
 
4057
      */
 
4058
      def= new Create_field(field, field);
 
4059
      new_create_list.push_back(def);
 
4060
      alter_it.rewind();                        // Change default if ALTER
 
4061
      Alter_column *alter;
 
4062
      while ((alter=alter_it++))
 
4063
        {
 
4064
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
4065
          break;
 
4066
        }
 
4067
      if (alter)
 
4068
        {
 
4069
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
 
4070
        {
 
4071
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
4072
          goto err;
 
4073
        }
 
4074
        if ((def->def=alter->def))              // Use new default
 
4075
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
 
4076
        else
 
4077
          def->flags|= NO_DEFAULT_VALUE_FLAG;
 
4078
        alter_it.remove();
 
4079
      }
 
4080
    }
 
4081
  }
 
4082
  def_it.rewind();
 
4083
  while ((def=def_it++))                        // Add new columns
 
4084
  {
 
4085
    if (def->change && ! def->field)
 
4086
    {
 
4087
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
4088
      goto err;
 
4089
    }
 
4090
      /*
 
4091
      Check that the DATE/DATETIME not null field we are going to add is
 
4092
      either has a default value or the '0000-00-00' is allowed by the
 
4093
      set sql mode.
 
4094
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
4095
      flag to allow ALTER Table only if the table to be altered is empty.
 
4096
      */
 
4097
    if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
 
4098
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
4099
         !alter_info->datetime_field &&
 
4100
         !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
4101
         thd->variables.sql_mode & MODE_NO_ZERO_DATE)
 
4102
    {
 
4103
        alter_info->datetime_field= def;
 
4104
        alter_info->error_if_not_empty= true;
 
4105
    }
 
4106
    if (!def->after)
 
4107
      new_create_list.push_back(def);
 
4108
    else if (def->after == first_keyword)
 
4109
      new_create_list.push_front(def);
 
4110
    else
 
4111
    {
 
4112
      Create_field *find;
 
4113
      find_it.rewind();
 
4114
      while ((find=find_it++))                  // Add new columns
 
4115
      {
 
4116
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
4117
          break;
 
4118
  }
 
4119
      if (!find)
 
4120
  {
 
4121
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
4122
    goto err;
 
4123
  }
 
4124
      find_it.after(def);                       // Put element after this
 
4125
      /*
 
4126
        XXX: hack for Bug#28427.
 
4127
        If column order has changed, force OFFLINE ALTER Table
 
4128
        without querying engine capabilities.  If we ever have an
 
4129
        engine that supports online ALTER Table CHANGE COLUMN
 
4130
        <name> AFTER <name1> (Falcon?), this fix will effectively
 
4131
        disable the capability.
 
4132
        TODO: detect the situation in compare_tables, behave based
 
4133
        on engine capabilities.
 
4134
      */
 
4135
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
4136
      {
 
4137
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
4138
        goto err;
 
4139
      }
 
4140
      alter_info->build_method= HA_BUILD_OFFLINE;
 
4141
    }
 
4142
  }
 
4143
  if (alter_info->alter_list.elements)
 
4144
  {
 
4145
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
4146
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
4147
    goto err;
 
4148
    }
 
4149
  if (!new_create_list.elements)
 
4150
    {
 
4151
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
 
4152
               MYF(0));
 
4153
    goto err;
 
4154
    }
 
4155
 
 
4156
    /*
 
4157
    Collect all keys which isn't in drop list. Add only those
 
4158
    for which some fields exists.
 
4159
    */
 
4160
 
 
4161
  for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
 
4162
    {
 
4163
    char *key_name= key_info->name;
 
4164
    Alter_drop *drop;
 
4165
    drop_it.rewind();
 
4166
    while ((drop=drop_it++))
 
4167
      {
 
4168
      if (drop->type == Alter_drop::KEY &&
 
4169
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
4170
        break;
 
4171
      }
 
4172
    if (drop)
 
4173
        {
 
4174
      drop_it.remove();
 
4175
      continue;
 
4176
    }
 
4177
 
 
4178
    KEY_PART_INFO *key_part= key_info->key_part;
 
4179
    key_parts.empty();
 
4180
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
4181
    {
 
4182
      if (!key_part->field)
 
4183
        continue;                               // Wrong field (from UNIREG)
 
4184
      const char *key_part_name=key_part->field->field_name;
 
4185
      Create_field *cfield;
 
4186
      field_it.rewind();
 
4187
      while ((cfield=field_it++))
 
4188
    {
 
4189
        if (cfield->change)
 
4190
    {
 
4191
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
4192
                             cfield->change))
 
4193
            break;
 
4194
        }
 
4195
        else if (!my_strcasecmp(system_charset_info,
 
4196
                                key_part_name, cfield->field_name))
 
4197
          break;
 
4198
      }
 
4199
      if (!cfield)
 
4200
        continue;                               // Field is removed
 
4201
      uint32_t key_part_length=key_part->length;
 
4202
      if (cfield->field)                        // Not new field
 
4203
      {
 
4204
        /*
 
4205
          If the field can't have only a part used in a key according to its
 
4206
          new type, or should not be used partially according to its
 
4207
          previous type, or the field length is less than the key part
 
4208
          length, unset the key part length.
 
4209
 
 
4210
          We also unset the key part length if it is the same as the
 
4211
          old field's length, so the whole new field will be used.
 
4212
 
 
4213
          BLOBs may have cfield->length == 0, which is why we test it before
 
4214
          checking whether cfield->length < key_part_length (in chars).
 
4215
         */
 
4216
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
4217
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
4218
            (cfield->field->field_length == key_part_length &&
 
4219
             !f_is_blob(key_part->key_type)) ||
 
4220
            (cfield->length && (cfield->length < key_part_length /
 
4221
                                key_part->field->charset()->mbmaxlen)))
 
4222
          key_part_length= 0;                   // Use whole field
 
4223
      }
 
4224
      key_part_length /= key_part->field->charset()->mbmaxlen;
 
4225
      key_parts.push_back(new Key_part_spec(cfield->field_name,
 
4226
                                            strlen(cfield->field_name),
 
4227
                                            key_part_length));
 
4228
    }
 
4229
    if (key_parts.elements)
 
4230
    {
 
4231
      KEY_CREATE_INFO key_create_info;
 
4232
      Key *key;
 
4233
      enum Key::Keytype key_type;
 
4234
      memset(&key_create_info, 0, sizeof(key_create_info));
 
4235
 
 
4236
      key_create_info.algorithm= key_info->algorithm;
 
4237
      if (key_info->flags & HA_USES_BLOCK_SIZE)
 
4238
        key_create_info.block_size= key_info->block_size;
 
4239
      if (key_info->flags & HA_USES_COMMENT)
 
4240
        key_create_info.comment= key_info->comment;
 
4241
 
 
4242
      if (key_info->flags & HA_NOSAME)
 
4243
      {
 
4244
        if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
 
4245
          key_type= Key::PRIMARY;
 
4246
        else
 
4247
          key_type= Key::UNIQUE;
 
4248
      }
 
4249
      else
 
4250
        key_type= Key::MULTIPLE;
 
4251
 
 
4252
      key= new Key(key_type, key_name, strlen(key_name),
 
4253
                   &key_create_info,
 
4254
                   test(key_info->flags & HA_GENERATED_KEY),
 
4255
                   key_parts);
 
4256
      new_key_list.push_back(key);
 
4257
    }
 
4258
  }
 
4259
  {
 
4260
    Key *key;
 
4261
    while ((key=key_it++))                      // Add new keys
 
4262
    {
 
4263
      if (key->type != Key::FOREIGN_KEY)
 
4264
        new_key_list.push_back(key);
 
4265
      if (key->name.str &&
 
4266
          !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
 
4267
      {
 
4268
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
4269
        goto err;
 
4270
      }
 
4271
    }
 
4272
  }
 
4273
 
 
4274
  if (alter_info->drop_list.elements)
 
4275
  {
 
4276
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
4277
             alter_info->drop_list.head()->name);
 
4278
    goto err;
 
4279
  }
 
4280
  if (alter_info->alter_list.elements)
 
4281
  {
 
4282
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
4283
             alter_info->alter_list.head()->name);
 
4284
    goto err;
 
4285
  }
 
4286
 
 
4287
  if (!create_info->comment.str)
 
4288
  {
 
4289
    create_info->comment.str= table->s->comment.str;
 
4290
    create_info->comment.length= table->s->comment.length;
 
4291
  }
 
4292
 
 
4293
  table->file->update_create_info(create_info);
 
4294
  if ((create_info->table_options &
 
4295
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
 
4296
      (used_fields & HA_CREATE_USED_PACK_KEYS))
 
4297
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
 
4298
  if (create_info->table_options &
 
4299
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
 
4300
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
 
4301
  if (create_info->table_options &
 
4302
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
 
4303
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
 
4304
                          HA_OPTION_NO_DELAY_KEY_WRITE);
 
4305
  create_info->table_options|= db_create_options;
 
4306
 
 
4307
  if (table->s->tmp_table)
 
4308
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
4309
 
 
4310
  rc= false;
 
4311
  alter_info->create_list.swap(new_create_list);
 
4312
  alter_info->key_list.swap(new_key_list);
 
4313
err:
 
4314
  return(rc);
 
4315
}
 
4316
 
 
4317
 
 
4318
/*
 
4319
  Alter table
 
4320
 
 
4321
  SYNOPSIS
 
4322
    mysql_alter_table()
 
4323
      thd              Thread handle
 
4324
      new_db           If there is a RENAME clause
 
4325
      new_name         If there is a RENAME clause
 
4326
      create_info      Information from the parsing phase about new
 
4327
                       table properties.
 
4328
      table_list       The table to change.
 
4329
      alter_info       Lists of fields, keys to be changed, added
 
4330
                       or dropped.
 
4331
      order_num        How many order_st BY fields has been specified.
 
4332
      order            List of fields to order_st BY.
 
4333
      ignore           Whether we have ALTER IGNORE Table
 
4334
 
 
4335
  DESCRIPTION
 
4336
    This is a veery long function and is everything but the kitchen sink :)
 
4337
    It is used to alter a table and not only by ALTER Table but also
 
4338
    CREATE|DROP INDEX are mapped on this function.
 
4339
 
 
4340
    When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
 
4341
    or both, then this function short cuts its operation by renaming
 
4342
    the table and/or enabling/disabling the keys. In this case, the FRM is
 
4343
    not changed, directly by mysql_alter_table. However, if there is a
 
4344
    RENAME + change of a field, or an index, the short cut is not used.
 
4345
    See how `create_list` is used to generate the new FRM regarding the
 
4346
    structure of the fields. The same is done for the indices of the table.
 
4347
 
 
4348
    Important is the fact, that this function tries to do as little work as
 
4349
    possible, by finding out whether a intermediate table is needed to copy
 
4350
    data into and when finishing the altering to use it as the original table.
 
4351
    For this reason the function compare_tables() is called, which decides
 
4352
    based on all kind of data how similar are the new and the original
 
4353
    tables.
 
4354
 
 
4355
  RETURN VALUES
 
4356
    false  OK
 
4357
    true   Error
 
4358
*/
 
4359
 
 
4360
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
 
4361
                       HA_CREATE_INFO *create_info,
 
4362
                       TableList *table_list,
 
4363
                       Alter_info *alter_info,
 
4364
                       uint32_t order_num, order_st *order, bool ignore)
 
4365
{
 
4366
  Table *table, *new_table=0, *name_lock= 0;;
 
4367
  int error= 0;
 
4368
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
 
4369
  char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
 
4370
  char path[FN_REFLEN];
 
4371
  ha_rows copied= 0,deleted= 0;
 
4372
  handlerton *old_db_type, *new_db_type, *save_old_db_type;
 
4373
  legacy_db_type table_type;
 
4374
 
 
4375
  if (table_list && table_list->schema_table)
 
4376
  {
 
4377
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
4378
    return(true);
 
4379
  }
 
4380
 
 
4381
  /*
 
4382
    Assign variables table_name, new_name, db, new_db, path
 
4383
    to simplify further comparisons: we want to see if it's a RENAME
 
4384
    later just by comparing the pointers, avoiding the need for strcmp.
 
4385
  */
 
4386
  thd->set_proc_info("init");
 
4387
  table_name=table_list->table_name;
 
4388
  alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
 
4389
  db=table_list->db;
 
4390
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
 
4391
    new_db= db;
 
4392
  build_table_filename(path, sizeof(path), db, table_name, "", 0);
 
4393
 
 
4394
  mysql_ha_rm_tables(thd, table_list, false);
 
4395
 
 
4396
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
4397
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
4398
    /* Conditionally writes to binlog. */
 
4399
    return(mysql_discard_or_import_tablespace(thd,table_list,
 
4400
                                              alter_info->tablespace_op));
 
4401
  strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, 
 
4402
           "/", table_name, reg_ext, NULL);
 
4403
  (void) unpack_filename(new_name_buff, new_name_buff);
 
4404
  /*
 
4405
    If this is just a rename of a view, short cut to the
 
4406
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
4407
    2) unlock LOCK_open.
 
4408
    This is a copy-paste added to make sure
 
4409
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
 
4410
    as an independent branch in mysql_execute_command. The need
 
4411
    for a copy-paste arose because the main code flow of ALTER Table
 
4412
    ... RENAME tries to use open_ltable, which does not work for views
 
4413
    (open_ltable was never modified to merge table lists of child tables
 
4414
    into the main table list, like open_tables does).
 
4415
    This code is wrong and will be removed, please do not copy.
 
4416
  */
 
4417
  (void)mysql_frm_type(thd, new_name_buff, &table_type);
 
4418
 
 
4419
  if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
 
4420
    return(true);
 
4421
  table->use_all_columns();
 
4422
 
 
4423
  /* Check that we are not trying to rename to an existing table */
 
4424
  if (new_name)
 
4425
  {
 
4426
    my_stpcpy(new_name_buff,new_name);
 
4427
    my_stpcpy(new_alias= new_alias_buff, new_name);
 
4428
    if (lower_case_table_names)
 
4429
    {
 
4430
      if (lower_case_table_names != 2)
 
4431
      {
 
4432
        my_casedn_str(files_charset_info, new_name_buff);
 
4433
        new_alias= new_name;                    // Create lower case table name
 
4434
      }
 
4435
      my_casedn_str(files_charset_info, new_name);
 
4436
    }
 
4437
    if (new_db == db &&
 
4438
        !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
4439
    {
 
4440
      /*
 
4441
        Source and destination table names are equal: make later check
 
4442
        easier.
 
4443
      */
 
4444
      new_alias= new_name= table_name;
 
4445
    }
 
4446
    else
 
4447
    {
 
4448
      if (table->s->tmp_table != NO_TMP_TABLE)
 
4449
      {
 
4450
        if (find_temporary_table(thd,new_db,new_name_buff))
 
4451
        {
 
4452
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
4453
          return(true);
 
4454
        }
 
4455
      }
 
4456
      else
 
4457
      {
 
4458
        if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
 
4459
          return(true);
 
4460
        if (!name_lock)
 
4461
        {
 
4462
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
4463
          return(true);
 
4464
        }
 
4465
 
 
4466
        build_table_filename(new_name_buff, sizeof(new_name_buff),
 
4467
                             new_db, new_name_buff, reg_ext, 0);
 
4468
        if (!access(new_name_buff, F_OK))
 
4469
        {
 
4470
          /* Table will be closed in do_command() */
 
4471
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
4472
          goto err;
 
4473
        }
 
4474
      }
 
4475
    }
 
4476
  }
 
4477
  else
 
4478
  {
 
4479
    new_alias= (lower_case_table_names == 2) ? alias : table_name;
 
4480
    new_name= table_name;
 
4481
  }
 
4482
 
 
4483
  old_db_type= table->s->db_type();
 
4484
  if (!create_info->db_type)
 
4485
  {
 
4486
    create_info->db_type= old_db_type;
 
4487
  }
 
4488
 
 
4489
  if (check_engine(thd, new_name, create_info))
 
4490
    goto err;
 
4491
  new_db_type= create_info->db_type;
 
4492
 
 
4493
  if (new_db_type != old_db_type &&
 
4494
      !table->file->can_switch_engines())
 
4495
  {
 
4496
    assert(0);
 
4497
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
 
4498
    goto err;
 
4499
  }
 
4500
 
 
4501
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
4502
    create_info->row_type= table->s->row_type;
 
4503
 
 
4504
  if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
 
4505
      ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
 
4506
  {
 
4507
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
4508
    goto err;
 
4509
  }
 
4510
 
 
4511
  thd->set_proc_info("setup");
 
4512
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
 
4513
      !table->s->tmp_table) // no need to touch frm
 
4514
  {
 
4515
    switch (alter_info->keys_onoff) {
 
4516
    case LEAVE_AS_IS:
 
4517
      break;
 
4518
    case ENABLE:
 
4519
      /*
 
4520
        wait_while_table_is_used() ensures that table being altered is
 
4521
        opened only by this thread and that Table::TABLE_SHARE::version
 
4522
        of Table object corresponding to this table is 0.
 
4523
        The latter guarantees that no DML statement will open this table
 
4524
        until ALTER Table finishes (i.e. until close_thread_tables())
 
4525
        while the fact that the table is still open gives us protection
 
4526
        from concurrent DDL statements.
 
4527
      */
 
4528
      pthread_mutex_lock(&LOCK_open);
 
4529
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
4530
      pthread_mutex_unlock(&LOCK_open);
 
4531
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4532
      /* COND_refresh will be signaled in close_thread_tables() */
 
4533
      break;
 
4534
    case DISABLE:
 
4535
      pthread_mutex_lock(&LOCK_open);
 
4536
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
4537
      pthread_mutex_unlock(&LOCK_open);
 
4538
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4539
      /* COND_refresh will be signaled in close_thread_tables() */
 
4540
      break;
 
4541
    default:
 
4542
      assert(false);
 
4543
      error= 0;
 
4544
      break;
 
4545
    }
 
4546
    if (error == HA_ERR_WRONG_COMMAND)
 
4547
    {
 
4548
      error= 0;
 
4549
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
4550
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
4551
                          table->alias);
 
4552
    }
 
4553
 
 
4554
    pthread_mutex_lock(&LOCK_open);
 
4555
    /*
 
4556
      Unlike to the above case close_cached_table() below will remove ALL
 
4557
      instances of Table from table cache (it will also remove table lock
 
4558
      held by this thread). So to make actual table renaming and writing
 
4559
      to binlog atomic we have to put them into the same critical section
 
4560
      protected by LOCK_open mutex. This also removes gap for races between
 
4561
      access() and mysql_rename_table() calls.
 
4562
    */
 
4563
 
 
4564
    if (!error && (new_name != table_name || new_db != db))
 
4565
    {
 
4566
      thd->set_proc_info("rename");
 
4567
      /*
 
4568
        Then do a 'simple' rename of the table. First we need to close all
 
4569
        instances of 'source' table.
 
4570
      */
 
4571
      close_cached_table(thd, table);
 
4572
      /*
 
4573
        Then, we want check once again that target table does not exist.
 
4574
        Actually the order of these two steps does not matter since
 
4575
        earlier we took name-lock on the target table, so we do them
 
4576
        in this particular order only to be consistent with 5.0, in which
 
4577
        we don't take this name-lock and where this order really matters.
 
4578
        TODO: Investigate if we need this access() check at all.
 
4579
      */
 
4580
      if (!access(new_name_buff,F_OK))
 
4581
      {
 
4582
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
4583
        error= -1;
 
4584
      }
 
4585
      else
 
4586
      {
 
4587
        *fn_ext(new_name)=0;
 
4588
        if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
 
4589
          error= -1;
 
4590
        else if (0)
 
4591
      {
 
4592
          mysql_rename_table(old_db_type, new_db, new_alias, db,
 
4593
                             table_name, 0);
 
4594
          error= -1;
 
4595
      }
 
4596
    }
 
4597
  }
 
4598
 
 
4599
    if (error == HA_ERR_WRONG_COMMAND)
 
4600
  {
 
4601
      error= 0;
 
4602
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
4603
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
4604
                          table->alias);
 
4605
  }
 
4606
 
 
4607
    if (!error)
 
4608
    {
 
4609
      write_bin_log(thd, true, thd->query, thd->query_length);
 
4610
      my_ok(thd);
 
4611
  }
 
4612
    else if (error > 0)
 
4613
  {
 
4614
      table->file->print_error(error, MYF(0));
 
4615
      error= -1;
 
4616
    }
2191
4617
    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)
 
4618
      unlink_open_table(thd, name_lock, false);
 
4619
    pthread_mutex_unlock(&LOCK_open);
 
4620
    table_list->table= NULL;                    // For query cache
 
4621
    return(error);
 
4622
  }
 
4623
 
 
4624
  /* We have to do full alter table. */
 
4625
 
 
4626
    /*
 
4627
    If the old table had partitions and we are doing ALTER Table ...
 
4628
    engine= <new_engine>, the new table must preserve the original
 
4629
    partitioning. That means that the new engine is still the
 
4630
    partitioning engine, not the engine specified in the parser.
 
4631
    This is discovered  in prep_alter_part_table, which in such case
 
4632
    updates create_info->db_type.
 
4633
    Now we need to update the stack copy of create_info->db_type,
 
4634
    as otherwise we won't be able to correctly move the files of the
 
4635
    temporary table to the result table files.
 
4636
  */
 
4637
  new_db_type= create_info->db_type;
 
4638
 
 
4639
  if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
 
4640
      goto err;
 
4641
 
 
4642
  set_table_default_charset(thd, create_info, db);
 
4643
 
 
4644
 
 
4645
  if (thd->variables.old_alter_table
 
4646
      || (table->s->db_type() != create_info->db_type)
 
4647
     )
 
4648
  {
 
4649
    if (alter_info->build_method == HA_BUILD_ONLINE)
 
4650
    {
 
4651
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
4652
      goto err;
 
4653
    }
 
4654
    alter_info->build_method= HA_BUILD_OFFLINE;
 
4655
  }
 
4656
 
 
4657
  if (alter_info->build_method != HA_BUILD_OFFLINE)
 
4658
  {
 
4659
    Table *altered_table= 0;
 
4660
    HA_ALTER_INFO ha_alter_info;
 
4661
    HA_ALTER_FLAGS ha_alter_flags;
 
4662
    uint32_t table_changes= IS_EQUAL_YES;
 
4663
    bool need_copy_table= true;
 
4664
    /* Check how much the tables differ. */
 
4665
    if (compare_tables(thd, table, alter_info,
 
4666
                       create_info, order_num,
 
4667
                       &ha_alter_flags,
 
4668
                       &ha_alter_info,
 
4669
                       &table_changes))
 
4670
    {
 
4671
      return(true);
 
4672
    }
 
4673
 
 
4674
    /*
 
4675
      Check if storage engine supports altering the table
 
4676
      on-line.
 
4677
    */
 
4678
 
 
4679
 
 
4680
    /*
 
4681
      If table is not renamed, changed database and
 
4682
      some change was detected then check if engine
 
4683
      can do the change on-line
 
4684
    */
 
4685
    if (new_name == table_name && new_db == db &&
 
4686
        ha_alter_flags.is_set())
 
4687
    {
 
4688
      Alter_info tmp_alter_info(*alter_info, thd->mem_root);
 
4689
 
 
4690
      /*
 
4691
        If no table rename,
 
4692
        check if table can be altered on-line
 
4693
      */
 
4694
      if (!(altered_table= create_altered_table(thd,
 
4695
                                                table,
 
4696
                                                new_db,
 
4697
                                                create_info,
 
4698
                                                &tmp_alter_info,
 
4699
                                                !strcmp(db, new_db))))
 
4700
        goto err;
 
4701
 
 
4702
      switch (table->file->check_if_supported_alter(altered_table,
 
4703
                                                    create_info,
 
4704
                                                    &ha_alter_flags,
 
4705
                                                    table_changes)) {
 
4706
      case HA_ALTER_SUPPORTED_WAIT_LOCK:
 
4707
      case HA_ALTER_SUPPORTED_NO_LOCK:
 
4708
        /*
 
4709
          @todo: Currently we always acquire an exclusive name
 
4710
          lock on the table metadata when performing fast or online
 
4711
          ALTER Table. In future we may consider this unnecessary,
 
4712
          and narrow the scope of the exclusive name lock to only
 
4713
          cover manipulation with .frms. Storage engine API
 
4714
          call check_if_supported_alter has provision for this
 
4715
          already now.
 
4716
        */
 
4717
        need_copy_table= false;
 
4718
        break;
 
4719
      case HA_ALTER_NOT_SUPPORTED:
 
4720
        if (alter_info->build_method == HA_BUILD_ONLINE)
 
4721
        {
 
4722
          my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
4723
          close_temporary_table(thd, altered_table, 1, 1);
 
4724
          goto err;
 
4725
        }
 
4726
        need_copy_table= true;
 
4727
        break;
 
4728
      case HA_ALTER_ERROR:
 
4729
      default:
 
4730
        close_temporary_table(thd, altered_table, 1, 1);
 
4731
        goto err;
 
4732
      }
 
4733
 
 
4734
    }
 
4735
    /* TODO need to check if changes can be handled as fast ALTER Table */
 
4736
    if (!altered_table)
 
4737
      need_copy_table= true;
 
4738
 
 
4739
    if (!need_copy_table)
 
4740
    {
 
4741
      error= mysql_fast_or_online_alter_table(thd,
 
4742
                                              table,
 
4743
                                              altered_table,
 
4744
                                              create_info,
 
4745
                                              &ha_alter_info,
 
4746
                                              &ha_alter_flags,
 
4747
                                              alter_info->keys_onoff);
 
4748
      if (thd->lock)
 
4749
      {
 
4750
        mysql_unlock_tables(thd, thd->lock);
 
4751
        thd->lock=0;
 
4752
      }
 
4753
      close_temporary_table(thd, altered_table, 1, 1);
 
4754
 
 
4755
      if (error)
 
4756
      {
 
4757
        switch (error) {
 
4758
        case(-1):
 
4759
          goto err_with_placeholders;
 
4760
        default:
 
4761
          goto err;
 
4762
        }
 
4763
      }
 
4764
      else
 
4765
      {
 
4766
        pthread_mutex_lock(&LOCK_open);
 
4767
        goto end_online;
 
4768
      }
 
4769
    }
 
4770
 
 
4771
    if (altered_table)
 
4772
      close_temporary_table(thd, altered_table, 1, 1);
 
4773
  }
 
4774
 
 
4775
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
 
4776
           current_pid, thd->thread_id);
 
4777
  /* Safety fix for innodb */
 
4778
  if (lower_case_table_names)
 
4779
    my_casedn_str(files_charset_info, tmp_name);
 
4780
 
 
4781
 
 
4782
  /* Create a temporary table with the new format */
 
4783
  if ((error= create_temporary_table(thd, table, new_db, tmp_name, 
 
4784
                                     create_info, alter_info, 
 
4785
                                     !strcmp(db, new_db))))
 
4786
  {
 
4787
    goto err;
 
4788
  }
 
4789
 
 
4790
  /* Open the table so we need to copy the data to it. */
 
4791
  if (table->s->tmp_table)
 
4792
  {
 
4793
    TableList tbl;
 
4794
    memset(&tbl, 0, sizeof(tbl));
 
4795
    tbl.db= new_db;
 
4796
    tbl.table_name= tbl.alias= tmp_name;
 
4797
    /* Table is in thd->temporary_tables */
 
4798
    new_table= open_table(thd, &tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
 
4799
  }
 
4800
  else
 
4801
  {
 
4802
    char path[FN_REFLEN];
 
4803
    /* table is a normal table: Create temporary table in same directory */
 
4804
    build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
4805
                         FN_IS_TMP);
 
4806
    /* Open our intermediate table */
 
4807
    new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
 
4808
  }
 
4809
  if (!new_table)
 
4810
    goto err1;
 
4811
 
 
4812
  /* Copy the data if necessary. */
 
4813
  thd->count_cuted_fields= CHECK_FIELD_WARN;    // calc cuted fields
 
4814
  thd->cuted_fields=0L;
 
4815
  thd->set_proc_info("copy to tmp table");
 
4816
  copied=deleted=0;
 
4817
  /*
 
4818
    We do not copy data for MERGE tables. Only the children have data.
 
4819
    MERGE tables have HA_NO_COPY_ON_ALTER set.
 
4820
  */
 
4821
  if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
 
4822
  {
 
4823
    /* We don't want update TIMESTAMP fields during ALTER Table. */
 
4824
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
4825
    new_table->next_number_field=new_table->found_next_number_field;
 
4826
    error= copy_data_between_tables(table, new_table,
 
4827
                                    alter_info->create_list, ignore,
 
4828
                                   order_num, order, &copied, &deleted,
 
4829
                                    alter_info->keys_onoff,
 
4830
                                    alter_info->error_if_not_empty);
 
4831
  }
 
4832
  else
 
4833
  {
 
4834
    pthread_mutex_lock(&LOCK_open);
 
4835
    wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
4836
    pthread_mutex_unlock(&LOCK_open);
 
4837
    alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
4838
                            alter_info->keys_onoff);
 
4839
    error= ha_autocommit_or_rollback(thd, 0);
 
4840
    if (end_active_trans(thd))
 
4841
      error= 1;
 
4842
  }
 
4843
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
4844
 
 
4845
  if (table->s->tmp_table != NO_TMP_TABLE)
 
4846
  {
 
4847
    /* We changed a temporary table */
 
4848
    if (error)
 
4849
      goto err1;
 
4850
    /* Close lock if this is a transactional table */
 
4851
    if (thd->lock)
 
4852
    {
 
4853
      mysql_unlock_tables(thd, thd->lock);
 
4854
      thd->lock=0;
 
4855
    }
 
4856
    /* Remove link to old table and rename the new one */
 
4857
    close_temporary_table(thd, table, 1, 1);
 
4858
    /* Should pass the 'new_name' as we store table name in the cache */
 
4859
    if (rename_temporary_table(thd, new_table, new_db, new_name))
 
4860
      goto err1;
 
4861
    /* We don't replicate alter table statement on temporary tables */
 
4862
    if (!thd->current_stmt_binlog_row_based)
 
4863
      write_bin_log(thd, true, thd->query, thd->query_length);
 
4864
    goto end_temporary;
 
4865
  }
 
4866
 
 
4867
  if (new_table)
 
4868
  {
 
4869
    /*
 
4870
      Close the intermediate table that will be the new table.
 
4871
      Note that MERGE tables do not have their children attached here.
 
4872
    */
 
4873
    intern_close_table(new_table);
 
4874
    free(new_table);
 
4875
  }
 
4876
  pthread_mutex_lock(&LOCK_open);
 
4877
  if (error)
 
4878
  {
 
4879
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
4880
    pthread_mutex_unlock(&LOCK_open);
 
4881
    goto err;
 
4882
  }
 
4883
 
 
4884
  /*
 
4885
    Data is copied. Now we:
 
4886
    1) Wait until all other threads close old version of table.
 
4887
    2) Close instances of table open by this thread and replace them
 
4888
       with exclusive name-locks.
 
4889
    3) Rename the old table to a temp name, rename the new one to the
 
4890
       old name.
 
4891
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
4892
       we reopen new version of table.
 
4893
    5) Write statement to the binary log.
 
4894
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
4895
       remove name-locks from list of open tables and table cache.
 
4896
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
4897
       call to remove name-locks from table cache and list of open table.
 
4898
  */
 
4899
 
 
4900
  thd->set_proc_info("rename result table");
 
4901
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
 
4902
           current_pid, thd->thread_id);
 
4903
  if (lower_case_table_names)
 
4904
    my_casedn_str(files_charset_info, old_name);
 
4905
 
 
4906
  wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
4907
  close_data_files_and_morph_locks(thd, db, table_name);
 
4908
 
 
4909
  error=0;
 
4910
  save_old_db_type= old_db_type;
 
4911
 
 
4912
  /*
 
4913
    This leads to the storage engine (SE) not being notified for renames in
 
4914
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
4915
    more. If we have an intermediate table, then we notify the SE that
 
4916
    it should become the actual table. Later, we will recycle the old table.
 
4917
    However, in case of ALTER Table RENAME there might be no intermediate
 
4918
    table. This is when the old and new tables are compatible, according to
 
4919
    compare_table(). Then, we need one additional call to
 
4920
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
4921
    actual rename in the SE and the FRM is not touched. Note that, if the
 
4922
    table is renamed and the SE is also changed, then an intermediate table
 
4923
    is created and the additional call will not take place.
 
4924
  */
 
4925
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
 
4926
                         FN_TO_IS_TMP))
 
4927
  {
 
4928
    error=1;
 
4929
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
4930
  }
 
4931
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
 
4932
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
 
4933
  {
 
4934
    /* Try to get everything back. */
 
4935
    error=1;
 
4936
    quick_rm_table(new_db_type,new_db,new_alias, 0);
 
4937
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
4938
    mysql_rename_table(old_db_type, db, old_name, db, alias,
 
4939
                       FN_FROM_IS_TMP);
 
4940
  }
 
4941
 
 
4942
  if (error)
 
4943
  {
 
4944
    /* This shouldn't happen. But let us play it safe. */
 
4945
    goto err_with_placeholders;
 
4946
  }
 
4947
 
 
4948
  quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
 
4949
 
 
4950
end_online:
 
4951
  if (thd->locked_tables && new_name == table_name && new_db == db)
 
4952
  {
 
4953
    thd->in_lock_tables= 1;
 
4954
    error= reopen_tables(thd, 1, 1);
 
4955
    thd->in_lock_tables= 0;
 
4956
    if (error)
 
4957
      goto err_with_placeholders;
 
4958
  }
 
4959
  pthread_mutex_unlock(&LOCK_open);
 
4960
 
 
4961
  thd->set_proc_info("end");
 
4962
 
 
4963
  assert(!(mysql_bin_log.is_open() &&
 
4964
                thd->current_stmt_binlog_row_based &&
 
4965
                (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
 
4966
  write_bin_log(thd, true, thd->query, thd->query_length);
 
4967
 
 
4968
  if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
 
4969
  {
 
4970
    /*
 
4971
      For the alter table to be properly flushed to the logs, we
 
4972
      have to open the new table.  If not, we get a problem on server
 
4973
      shutdown. But we do not need to attach MERGE children.
 
4974
    */
 
4975
    char path[FN_REFLEN];
 
4976
    Table *t_table;
 
4977
    build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
 
4978
    t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
 
4979
    if (t_table)
 
4980
    {
 
4981
      intern_close_table(t_table);
 
4982
      free(t_table);
 
4983
    }
 
4984
    else
 
4985
      sql_print_warning(_("Could not open table %s.%s after rename\n"),
 
4986
                        new_db,table_name);
 
4987
    ha_flush_logs(old_db_type);
 
4988
  }
 
4989
  table_list->table=0;                          // For query cache
 
4990
 
 
4991
  if (thd->locked_tables && (new_name != table_name || new_db != db))
 
4992
  {
 
4993
    /*
 
4994
      If are we under LOCK TABLES and did ALTER Table with RENAME we need
 
4995
      to remove placeholders for the old table and for the target table
 
4996
      from the list of open tables and table cache. If we are not under
 
4997
      LOCK TABLES we can rely on close_thread_tables() doing this job.
 
4998
    */
 
4999
    pthread_mutex_lock(&LOCK_open);
 
5000
    unlink_open_table(thd, table, false);
 
5001
    unlink_open_table(thd, name_lock, false);
 
5002
    pthread_mutex_unlock(&LOCK_open);
 
5003
  }
 
5004
 
 
5005
end_temporary:
 
5006
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
5007
           (ulong) (copied + deleted), (ulong) deleted,
 
5008
           (ulong) thd->cuted_fields);
 
5009
  my_ok(thd, copied + deleted, 0L, tmp_name);
 
5010
  thd->some_tables_deleted=0;
 
5011
  return(false);
 
5012
 
 
5013
err1:
 
5014
  if (new_table)
 
5015
  {
 
5016
    /* close_temporary_table() frees the new_table pointer. */
 
5017
    close_temporary_table(thd, new_table, 1, 1);
 
5018
  }
 
5019
  else
 
5020
    quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
 
5021
 
 
5022
err:
 
5023
  /*
 
5024
    No default value was provided for a DATE/DATETIME field, the
 
5025
    current sql_mode doesn't allow the '0000-00-00' value and
 
5026
    the table to be altered isn't empty.
 
5027
    Report error here.
 
5028
  */
 
5029
  if (alter_info->error_if_not_empty && thd->row_count)
 
5030
  {
 
5031
    const char *f_val= 0;
 
5032
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
5033
    switch (alter_info->datetime_field->sql_type)
 
5034
    {
 
5035
      case DRIZZLE_TYPE_NEWDATE:
 
5036
        f_val= "0000-00-00";
 
5037
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
5038
        break;
 
5039
      case DRIZZLE_TYPE_DATETIME:
 
5040
        f_val= "0000-00-00 00:00:00";
 
5041
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
5042
        break;
 
5043
      default:
 
5044
        /* Shouldn't get here. */
 
5045
        assert(0);
 
5046
    }
 
5047
    bool save_abort_on_warning= thd->abort_on_warning;
 
5048
    thd->abort_on_warning= true;
 
5049
    make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
5050
                                 f_val, strlength(f_val), t_type,
 
5051
                                 alter_info->datetime_field->field_name);
 
5052
    thd->abort_on_warning= save_abort_on_warning;
 
5053
  }
 
5054
  if (name_lock)
 
5055
  {
 
5056
    pthread_mutex_lock(&LOCK_open);
 
5057
    unlink_open_table(thd, name_lock, false);
 
5058
    pthread_mutex_unlock(&LOCK_open);
 
5059
  }
 
5060
  return(true);
 
5061
 
 
5062
err_with_placeholders:
 
5063
  /*
 
5064
    An error happened while we were holding exclusive name-lock on table
 
5065
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
5066
    from list of open tables list and table cache.
 
5067
  */
 
5068
  unlink_open_table(thd, table, false);
 
5069
  if (name_lock)
 
5070
    unlink_open_table(thd, name_lock, false);
 
5071
  pthread_mutex_unlock(&LOCK_open);
 
5072
  return(true);
 
5073
}
 
5074
/* mysql_alter_table */
 
5075
 
 
5076
static int
 
5077
copy_data_between_tables(Table *from,Table *to,
 
5078
                         List<Create_field> &create,
 
5079
                         bool ignore,
 
5080
                         uint32_t order_num, order_st *order,
 
5081
                         ha_rows *copied,
 
5082
                         ha_rows *deleted,
 
5083
                         enum enum_enable_or_disable keys_onoff,
 
5084
                         bool error_if_not_empty)
 
5085
{
 
5086
  int error;
 
5087
  Copy_field *copy,*copy_end;
 
5088
  ulong found_count,delete_count;
 
5089
  THD *thd= current_thd;
 
5090
  uint32_t length= 0;
 
5091
  SORT_FIELD *sortorder;
 
5092
  READ_RECORD info;
 
5093
  TableList   tables;
 
5094
  List<Item>   fields;
 
5095
  List<Item>   all_fields;
 
5096
  ha_rows examined_rows;
 
5097
  bool auto_increment_field_copied= 0;
 
5098
  ulong save_sql_mode;
 
5099
  uint64_t prev_insert_id;
 
5100
 
 
5101
  /*
 
5102
    Turn off recovery logging since rollback of an alter table is to
 
5103
    delete the new table so there is no need to log the changes to it.
 
5104
    
 
5105
    This needs to be done before external_lock
 
5106
  */
 
5107
  error= ha_enable_transaction(thd, false);
 
5108
  if (error)
 
5109
    return(-1);
 
5110
  
 
5111
  if (!(copy= new Copy_field[to->s->fields]))
 
5112
    return(-1);                         /* purecov: inspected */
 
5113
 
 
5114
  if (to->file->ha_external_lock(thd, F_WRLCK))
 
5115
    return(-1);
 
5116
 
 
5117
  /* We need external lock before we can disable/enable keys */
 
5118
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
5119
 
 
5120
  /* We can abort alter table for any table type */
 
5121
  thd->abort_on_warning= !ignore;
 
5122
 
 
5123
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
5124
  to->file->ha_start_bulk_insert(from->file->stats.records);
 
5125
 
 
5126
  save_sql_mode= thd->variables.sql_mode;
 
5127
 
 
5128
  List_iterator<Create_field> it(create);
 
5129
  Create_field *def;
 
5130
  copy_end=copy;
 
5131
  for (Field **ptr=to->field ; *ptr ; ptr++)
 
5132
  {
 
5133
    def=it++;
 
5134
    if (def->field)
 
5135
    {
 
5136
      if (*ptr == to->next_number_field)
 
5137
        auto_increment_field_copied= true;
 
5138
 
 
5139
      (copy_end++)->set(*ptr,def->field,0);
 
5140
    }
 
5141
 
 
5142
  }
 
5143
 
 
5144
  found_count=delete_count=0;
 
5145
 
 
5146
  if (order)
 
5147
  {
 
5148
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2201
5149
    {
2202
5150
      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
 
 
 
5151
      snprintf(warn_buff, sizeof(warn_buff), 
 
5152
               _("order_st BY ignored because there is a user-defined clustered "
 
5153
                 "index in the table '%-.192s'"),
 
5154
               from->s->table_name.str);
 
5155
      push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
5156
                   warn_buff);
 
5157
    }
 
5158
    else
 
5159
    {
 
5160
      from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
 
5161
                                                MYF(MY_FAE | MY_ZEROFILL));
 
5162
      memset(&tables, 0, sizeof(tables));
 
5163
      tables.table= from;
 
5164
      tables.alias= tables.table_name= from->s->table_name.str;
 
5165
      tables.db= from->s->db.str;
 
5166
      error= 1;
 
5167
 
 
5168
      if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
 
5169
          setup_order(thd, thd->lex->select_lex.ref_pointer_array,
 
5170
                      &tables, fields, all_fields, order) ||
 
5171
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
5172
          (from->sort.found_records= filesort(thd, from, sortorder, length,
 
5173
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
5174
                                              1, &examined_rows)) ==
 
5175
          HA_POS_ERROR)
 
5176
        goto err;
 
5177
    }
 
5178
  };
 
5179
 
 
5180
  /* Tell handler that we have values for all columns in the to table */
 
5181
  to->use_all_columns();
 
5182
  init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
 
5183
  if (ignore)
 
5184
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
5185
  thd->row_count= 0;
 
5186
  restore_record(to, s->default_values);        // Create empty record
 
5187
  while (!(error=info.read_record(&info)))
 
5188
  {
 
5189
    if (thd->killed)
 
5190
    {
 
5191
      thd->send_kill_message();
 
5192
      error= 1;
 
5193
      break;
 
5194
    }
 
5195
    thd->row_count++;
 
5196
    /* Return error if source table isn't empty. */
 
5197
    if (error_if_not_empty)
 
5198
    {
 
5199
      error= 1;
 
5200
      break;
 
5201
    }
 
5202
    if (to->next_number_field)
 
5203
    {
 
5204
      if (auto_increment_field_copied)
 
5205
        to->auto_increment_field_not_null= true;
 
5206
      else
 
5207
        to->next_number_field->reset();
 
5208
    }
 
5209
    
 
5210
    for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
5211
    {
 
5212
      copy_ptr->do_copy(copy_ptr);
 
5213
    }
 
5214
    prev_insert_id= to->file->next_insert_id;
 
5215
    error=to->file->ha_write_row(to->record[0]);
 
5216
    to->auto_increment_field_not_null= false;
 
5217
    if (error)
 
5218
    {
 
5219
      if (!ignore ||
 
5220
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
5221
      {
 
5222
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
5223
         {
 
5224
           uint32_t key_nr= to->file->get_dup_key(error);
 
5225
           if ((int) key_nr >= 0)
 
5226
           {
 
5227
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
5228
             if (key_nr == 0 &&
 
5229
                 (to->key_info[0].key_part[0].field->flags &
 
5230
                  AUTO_INCREMENT_FLAG))
 
5231
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
5232
             to->file->print_keydup_error(key_nr, err_msg);
 
5233
             break;
 
5234
           }
 
5235
         }
 
5236
 
 
5237
        to->file->print_error(error,MYF(0));
 
5238
        break;
 
5239
      }
 
5240
      to->file->restore_auto_increment(prev_insert_id);
 
5241
      delete_count++;
 
5242
    }
 
5243
    else
 
5244
      found_count++;
 
5245
  }
 
5246
  end_read_record(&info);
 
5247
  free_io_cache(from);
 
5248
  delete [] copy;                               // This is never 0
 
5249
 
 
5250
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
5251
  {
 
5252
    to->file->print_error(my_errno,MYF(0));
 
5253
    error=1;
 
5254
  }
 
5255
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
5256
 
 
5257
  if (ha_enable_transaction(thd, true))
 
5258
  {
 
5259
    error= 1;
 
5260
    goto err;
 
5261
  }
 
5262
 
 
5263
  /*
 
5264
    Ensure that the new table is saved properly to disk so that we
 
5265
    can do a rename
 
5266
  */
 
5267
  if (ha_autocommit_or_rollback(thd, 0))
 
5268
    error=1;
 
5269
  if (end_active_trans(thd))
 
5270
    error=1;
 
5271
 
 
5272
 err:
 
5273
  thd->variables.sql_mode= save_sql_mode;
 
5274
  thd->abort_on_warning= 0;
 
5275
  free_io_cache(from);
 
5276
  *copied= found_count;
 
5277
  *deleted=delete_count;
 
5278
  to->file->ha_release_auto_increment();
 
5279
  if (to->file->ha_external_lock(thd,F_UNLCK))
 
5280
    error=1;
 
5281
  return(error > 0 ? -1 : 0);
 
5282
}
 
5283
 
 
5284
 
 
5285
/*
 
5286
  Recreates tables by calling mysql_alter_table().
 
5287
 
 
5288
  SYNOPSIS
 
5289
    mysql_recreate_table()
 
5290
    thd                 Thread handler
 
5291
    tables              Tables to recreate
 
5292
 
 
5293
 RETURN
 
5294
    Like mysql_alter_table().
 
5295
*/
 
5296
bool mysql_recreate_table(THD *thd, TableList *table_list)
 
5297
{
 
5298
  HA_CREATE_INFO create_info;
 
5299
  Alter_info alter_info;
 
5300
 
 
5301
  assert(!table_list->next_global);
 
5302
  /*
 
5303
    table_list->table has been closed and freed. Do not reference
 
5304
    uninitialized data. open_tables() could fail.
 
5305
  */
 
5306
  table_list->table= NULL;
 
5307
 
 
5308
  memset(&create_info, 0, sizeof(create_info));
 
5309
  create_info.row_type=ROW_TYPE_NOT_USED;
 
5310
  create_info.default_table_charset=default_charset_info;
 
5311
  /* Force alter table to recreate table */
 
5312
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
5313
  return(mysql_alter_table(thd, NULL, NULL, &create_info,
 
5314
                                table_list, &alter_info, 0,
 
5315
                                (order_st *) 0, 0));
 
5316
}
 
5317
 
 
5318
 
 
5319
bool mysql_checksum_table(THD *thd, TableList *tables,
 
5320
                          HA_CHECK_OPT *check_opt)
 
5321
{
 
5322
  TableList *table;
 
5323
  List<Item> field_list;
 
5324
  Item *item;
 
5325
  Protocol *protocol= thd->protocol;
 
5326
 
 
5327
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
5328
  item->maybe_null= 1;
 
5329
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
5330
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
5331
  item->maybe_null= 1;
 
5332
  if (protocol->send_fields(&field_list,
 
5333
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
5334
    return(true);
 
5335
 
 
5336
  /* Open one table after the other to keep lock time as short as possible. */
 
5337
  for (table= tables; table; table= table->next_local)
 
5338
  {
 
5339
    char table_name[NAME_LEN*2+2];
 
5340
    Table *t;
 
5341
 
 
5342
    strxmov(table_name, table->db ,".", table->table_name, NULL);
 
5343
 
 
5344
    t= table->table= open_n_lock_single_table(thd, table, TL_READ);
 
5345
    thd->clear_error();                 // these errors shouldn't get client
 
5346
 
 
5347
    protocol->prepare_for_resend();
 
5348
    protocol->store(table_name, system_charset_info);
 
5349
 
 
5350
    if (!t)
 
5351
    {
 
5352
      /* Table didn't exist */
 
5353
      protocol->store_null();
 
5354
      thd->clear_error();
 
5355
    }
 
5356
    else
 
5357
    {
 
5358
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
5359
          !(check_opt->flags & T_EXTEND))
 
5360
        protocol->store((uint64_t)t->file->checksum());
 
5361
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
5362
               (check_opt->flags & T_QUICK))
 
5363
        protocol->store_null();
 
5364
      else
 
5365
      {
 
5366
        /* calculating table's checksum */
 
5367
        ha_checksum crc= 0;
 
5368
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
5369
 
 
5370
        t->use_all_columns();
 
5371
 
 
5372
        if (t->file->ha_rnd_init(1))
 
5373
          protocol->store_null();
 
5374
        else
 
5375
        {
 
5376
          for (;;)
 
5377
          {
 
5378
            ha_checksum row_crc= 0;
 
5379
            int error= t->file->rnd_next(t->record[0]);
 
5380
            if (unlikely(error))
 
5381
            {
 
5382
              if (error == HA_ERR_RECORD_DELETED)
 
5383
                continue;
 
5384
              break;
 
5385
            }
 
5386
            if (t->s->null_bytes)
 
5387
            {
 
5388
              /* fix undefined null bits */
 
5389
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
5390
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
5391
                t->record[0][0] |= 1;
 
5392
 
 
5393
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
5394
            }
 
5395
 
 
5396
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
5397
            {
 
5398
              Field *f= t->field[i];
 
5399
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
5400
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
5401
              {
 
5402
                String tmp;
 
5403
                f->val_str(&tmp);
 
5404
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
5405
              }
 
5406
              else
 
5407
                row_crc= my_checksum(row_crc, f->ptr,
 
5408
                                     f->pack_length());
 
5409
            }
 
5410
 
 
5411
            crc+= row_crc;
 
5412
          }
 
5413
          protocol->store((uint64_t)crc);
 
5414
          t->file->ha_rnd_end();
 
5415
        }
 
5416
      }
 
5417
      thd->clear_error();
 
5418
      close_thread_tables(thd);
 
5419
      table->table=0;                           // For query cache
 
5420
    }
 
5421
    if (protocol->write())
 
5422
      goto err;
 
5423
  }
 
5424
 
 
5425
  my_eof(thd);
 
5426
  return(false);
 
5427
 
 
5428
 err:
 
5429
  close_thread_tables(thd);                     // Shouldn't be needed
 
5430
  if (table)
 
5431
    table->table=0;
 
5432
  return(true);
 
5433
}
 
5434
 
 
5435
static bool check_engine(THD *thd, const char *table_name,
 
5436
                         HA_CREATE_INFO *create_info)
 
5437
{
 
5438
  handlerton **new_engine= &create_info->db_type;
 
5439
  handlerton *req_engine= *new_engine;
 
5440
  bool no_substitution= 1;
 
5441
  if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
 
5442
                                  no_substitution, 1)))
2212
5443
    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 */
 
5444
 
 
5445
  if (req_engine && req_engine != *new_engine)
 
5446
  {
 
5447
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
5448
                       ER_WARN_USING_OTHER_HANDLER,
 
5449
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
5450
                       ha_resolve_storage_engine_name(*new_engine),
 
5451
                       table_name);
 
5452
  }
 
5453
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
5454
      ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
 
5455
  {
 
5456
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
5457
    {
 
5458
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
5459
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
 
5460
      *new_engine= 0;
 
5461
      return true;
 
5462
    }
 
5463
    *new_engine= myisam_hton;
 
5464
  }
 
5465
  return false;
 
5466
}