~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2008-08-01 22:33:44 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080801223344-vzhlflfmtijp1imv
First pass at gettexizing the error messages.

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