~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Lee
  • Date: 2008-10-30 22:02:01 UTC
  • mto: (572.1.2 devel)
  • mto: This revision was merged to the branch mainline in revision 573.
  • Revision ID: lbieber@lbieber-desktop-20081030220201-elb6qprbzpn7c5a4
add my name to the AUTHORS file

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