~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty
  • Date: 2008-11-07 05:51:15 UTC
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: mordred@palanthas.inaugust.com-20081107055115-0275gvq62buzls77
Fixed a decimal sign thing.

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