~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2009-07-10 01:49:29 UTC
  • mto: (1090.1.1 staging)
  • mto: This revision was merged to the branch mainline in revision 1091.
  • Revision ID: brian@gaz-20090710014929-v8pmvf7woqkld9iv
Cleanup of user_var

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"
 
18
#include <drizzled/server_includes.h>
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/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>
 
25
#include <mysys/hash.h>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
 
#include "drizzled/strfunc.h"
30
29
#include <drizzled/db.h>
31
30
#include <drizzled/lock.h>
32
31
#include <drizzled/unireg.h>
33
32
#include <drizzled/item/int.h>
34
33
#include <drizzled/item/empty_string.h>
35
34
#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
35
 
51
36
#include <algorithm>
52
 
#include <sstream>
53
 
 
54
 
#include <boost/unordered_set.hpp>
55
37
 
56
38
using namespace std;
57
 
 
58
 
namespace drizzled
59
 
{
60
 
 
61
 
extern pid_t current_pid;
62
 
 
63
 
bool is_primary_key(KeyInfo *key_info)
 
39
extern drizzled::TransactionServices transaction_services;
 
40
 
 
41
static const char hexchars[]= "0123456789abcdef";
 
42
bool is_primary_key(KEY *key_info)
64
43
{
65
44
  static const char * primary_key_name="PRIMARY";
66
45
  return (strcmp(key_info->name, primary_key_name)==0);
75
54
    return NULL;
76
55
}
77
56
 
78
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
79
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
 
57
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
58
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
 
59
static int copy_data_between_tables(Table *from,Table *to,
 
60
                                    List<CreateField> &create, bool ignore,
 
61
                                    uint32_t order_num, order_st *order,
 
62
                                    ha_rows *copied,ha_rows *deleted,
 
63
                                    enum enum_enable_or_disable keys_onoff,
 
64
                                    bool error_if_not_empty);
80
65
 
81
66
static bool prepare_blob_field(Session *session, CreateField *sql_field);
 
67
static bool check_engine(Session *, const char *, HA_CREATE_INFO *);
 
68
static int
 
69
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
 
70
                           Alter_info *alter_info,
 
71
                           bool tmp_table,
 
72
                               uint32_t *db_options,
 
73
                               handler *file, KEY **key_info_buffer,
 
74
                               uint32_t *key_count, int select_field_count);
 
75
static bool
 
76
mysql_prepare_alter_table(Session *session, Table *table,
 
77
                          HA_CREATE_INFO *create_info,
 
78
                          Alter_info *alter_info);
82
79
 
83
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
 
80
static void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
84
81
{
85
82
  /*
86
83
    If the table character set was not given explicitly,
87
84
    let's fetch the database default character set and
88
85
    apply it to the table.
89
86
  */
90
 
  SchemaIdentifier identifier(db);
91
87
  if (create_info->default_table_charset == NULL)
92
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
88
    create_info->default_table_charset= get_default_db_collation(db);
 
89
}
 
90
 
 
91
/*
 
92
  Translate a file name to a table name (WL #1324).
 
93
 
 
94
  SYNOPSIS
 
95
    filename_to_tablename()
 
96
      from                      The file name
 
97
      to                OUT     The table name
 
98
      to_length                 The size of the table name buffer.
 
99
 
 
100
  RETURN
 
101
    Table name length.
 
102
*/
 
103
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
104
{
 
105
  uint32_t length= 0;
 
106
 
 
107
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
108
  {
 
109
    /* Temporary table name. */
 
110
    length= strlen(strncpy(to, from, to_length));
 
111
  }
 
112
  else
 
113
  {
 
114
    for (; *from  && length < to_length; length++, from++)
 
115
    {
 
116
      if (*from != '@')
 
117
      {
 
118
        to[length]= *from;
 
119
        continue;
 
120
      }
 
121
      /* We've found an escaped char - skip the @ */
 
122
      from++;
 
123
      to[length]= 0;
 
124
      /* There will be a two-position hex-char version of the char */
 
125
      for (int x=1; x >= 0; x--)
 
126
      {
 
127
        if (*from >= '0' && *from <= '9')
 
128
          to[length] += ((*from++ - '0') << (4 * x));
 
129
        else if (*from >= 'a' && *from <= 'f')
 
130
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
131
      }
 
132
      /* Backup because we advanced extra in the inner loop */
 
133
      from--;
 
134
    } 
 
135
  }
 
136
 
 
137
  return length;
 
138
}
 
139
 
 
140
 
 
141
/*
 
142
  Translate a table name to a file name (WL #1324).
 
143
 
 
144
  SYNOPSIS
 
145
    tablename_to_filename()
 
146
      from                      The table name
 
147
      to                OUT     The file name
 
148
      to_length                 The size of the file name buffer.
 
149
 
 
150
  RETURN
 
151
    true if errors happen. false on success.
 
152
*/
 
153
bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
154
{
 
155
  
 
156
  size_t length= 0;
 
157
  for (; *from  && length < to_length; length++, from++)
 
158
  {
 
159
    if ((*from >= '0' && *from <= '9') ||
 
160
        (*from >= 'A' && *from <= 'Z') ||
 
161
        (*from >= 'a' && *from <= 'z') ||
 
162
/* OSX defines an extra set of high-bit and multi-byte characters
 
163
   that cannot be used on the filesystem. Instead of trying to sort
 
164
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
165
   It won't really hurt anything - it'll just make some filenames ugly. */
 
166
#if !defined(TARGET_OS_OSX)
 
167
        ((unsigned char)*from >= 128) ||
 
168
#endif
 
169
        (*from == '_') ||
 
170
        (*from == ' ') ||
 
171
        (*from == '-'))
 
172
    {
 
173
      to[length]= *from;
 
174
      continue;
 
175
    }
 
176
   
 
177
    if (length + 3 >= to_length)
 
178
      return true;
 
179
 
 
180
    /* We need to escape this char in a way that can be reversed */
 
181
    to[length++]= '@';
 
182
    to[length++]= hexchars[(*from >> 4) & 15];
 
183
    to[length]= hexchars[(*from) & 15];
 
184
  }
 
185
 
 
186
  if (check_if_legal_tablename(to) &&
 
187
      length + 4 < to_length)
 
188
  {
 
189
    memcpy(to + length, "@@@", 4);
 
190
    length+= 3;
 
191
  }
 
192
  return false;
 
193
}
 
194
 
 
195
 
 
196
/*
 
197
  Creates path to a file: drizzle_data_dir/db/table.ext
 
198
 
 
199
  SYNOPSIS
 
200
   build_table_filename()
 
201
     buff                       Where to write result
 
202
                                This may be the same as table_name.
 
203
     bufflen                    buff size
 
204
     db                         Database name
 
205
     table_name                 Table name
 
206
     ext                        File extension.
 
207
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
208
                                table_name is temporary, do not change.
 
209
 
 
210
  NOTES
 
211
 
 
212
    Uses database and table name, and extension to create
 
213
    a file name in drizzle_data_dir. Database and table
 
214
    names are converted from system_charset_info into "fscs".
 
215
    Unless flags indicate a temporary table name.
 
216
    'db' is always converted.
 
217
    'ext' is not converted.
 
218
 
 
219
    The conversion suppression is required for ALTER Table. This
 
220
    statement creates intermediate tables. These are regular
 
221
    (non-temporary) tables with a temporary name. Their path names must
 
222
    be derivable from the table name. So we cannot use
 
223
    build_tmptable_filename() for them.
 
224
 
 
225
  RETURN
 
226
    path length on success, 0 on failure
 
227
*/
 
228
 
 
229
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
 
230
{
 
231
  char dbbuff[FN_REFLEN];
 
232
  char tbbuff[FN_REFLEN];
 
233
  bool conversion_error= false;
 
234
 
 
235
  memset(tbbuff, 0, sizeof(tbbuff));
 
236
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
237
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
238
  else
 
239
  {
 
240
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
241
    if (conversion_error)
 
242
    {
 
243
      errmsg_printf(ERRMSG_LVL_ERROR,
 
244
                    _("Table name cannot be encoded and fit within filesystem "
 
245
                      "name length restrictions."));
 
246
      return 0;
 
247
    }
 
248
  }
 
249
  memset(dbbuff, 0, sizeof(dbbuff));
 
250
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
251
  if (conversion_error)
 
252
  {
 
253
    errmsg_printf(ERRMSG_LVL_ERROR,
 
254
                  _("Schema name cannot be encoded and fit within filesystem "
 
255
                    "name length restrictions."));
 
256
    return 0;
 
257
  }
 
258
   
 
259
 
 
260
  int rootdir_len= strlen(FN_ROOTDIR);
 
261
  string table_path(drizzle_data_home);
 
262
  int without_rootdir= table_path.length()-rootdir_len;
 
263
 
 
264
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
265
  if (without_rootdir >= 0)
 
266
  {
 
267
    const char *tmp= table_path.c_str()+without_rootdir;
 
268
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
269
      table_path.append(FN_ROOTDIR);
 
270
  }
 
271
 
 
272
  table_path.append(dbbuff);
 
273
  table_path.append(FN_ROOTDIR);
 
274
  table_path.append(tbbuff);
 
275
 
 
276
  if (bufflen < table_path.length())
 
277
    return 0;
 
278
 
 
279
  strcpy(buff, table_path.c_str());
 
280
 
 
281
  return table_path.length();
 
282
}
 
283
 
 
284
 
 
285
/*
 
286
  Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
 
287
 
 
288
  SYNOPSIS
 
289
   build_tmptable_filename()
 
290
     session                    The thread handle.
 
291
     buff                       Where to write result
 
292
     bufflen                    buff size
 
293
 
 
294
  NOTES
 
295
 
 
296
    Uses current_pid, thread_id, and tmp_table counter to create
 
297
    a file name in drizzle_tmpdir.
 
298
 
 
299
  RETURN
 
300
    path length on success, 0 on failure
 
301
*/
 
302
 
 
303
uint32_t build_tmptable_filename(Session* session, char *buff, size_t bufflen)
 
304
{
 
305
  uint32_t length;
 
306
  ostringstream path_str, post_tmpdir_str;
 
307
  string tmp;
 
308
 
 
309
  path_str << drizzle_tmpdir;
 
310
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
311
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
312
  tmp= post_tmpdir_str.str();
 
313
 
 
314
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
315
 
 
316
  path_str << tmp;
 
317
 
 
318
  if (bufflen < path_str.str().length())
 
319
    length= 0;
 
320
  else
 
321
    length= unpack_filename(buff, path_str.str().c_str());
 
322
 
 
323
  return length;
93
324
}
94
325
 
95
326
/*
96
327
  SYNOPSIS
97
328
    write_bin_log()
98
329
    session                           Thread object
 
330
    clear_error                   is clear_error to be called
99
331
    query                         Query to log
100
332
    query_length                  Length of query
101
333
 
104
336
 
105
337
  DESCRIPTION
106
338
    Write the binlog if open, routine used in multiple places in this
107
 
    cursor
108
 
*/
109
 
 
110
 
void write_bin_log(Session *session, const std::string &query)
111
 
{
112
 
  TransactionServices &transaction_services= TransactionServices::singleton();
113
 
  transaction_services.rawStatement(session, query);
 
339
    file
 
340
*/
 
341
 
 
342
void write_bin_log(Session *session, bool,
 
343
                   char const *query, size_t query_length)
 
344
{
 
345
  transaction_services.rawStatement(session, query, query_length);
 
346
}
 
347
 
 
348
 
 
349
/*
 
350
 delete (drop) tables.
 
351
 
 
352
  SYNOPSIS
 
353
   mysql_rm_table()
 
354
   session                      Thread handle
 
355
   tables               List of tables to delete
 
356
   if_exists            If 1, don't give error if one table doesn't exists
 
357
 
 
358
  NOTES
 
359
    Will delete all tables that can be deleted and give a compact error
 
360
    messages for tables that could not be deleted.
 
361
    If a table is in use, we will wait for all users to free the table
 
362
    before dropping it
 
363
 
 
364
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
365
    not if under LOCK TABLES.
 
366
 
 
367
  RETURN
 
368
    false OK.  In this case ok packet is sent to user
 
369
    true  Error
 
370
 
 
371
*/
 
372
 
 
373
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
 
374
{
 
375
  bool error, need_start_waiting= false;
 
376
 
 
377
  if (tables && tables->schema_table)
 
378
  {
 
379
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
380
    return(true);
 
381
  }
 
382
 
 
383
  /* mark for close and remove all cached entries */
 
384
 
 
385
  if (!drop_temporary)
 
386
  {
 
387
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
388
      return(true);
 
389
  }
 
390
 
 
391
  /*
 
392
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
393
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
394
    close their tables. This would make a pretty deadlock.
 
395
  */
 
396
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, 0);
 
397
 
 
398
  if (need_start_waiting)
 
399
    start_waiting_global_read_lock(session);
 
400
 
 
401
  if (error)
 
402
    return(true);
 
403
  session->my_ok();
 
404
  return(false);
114
405
}
115
406
 
116
407
/*
118
409
 
119
410
  SYNOPSIS
120
411
    mysql_rm_table_part2()
121
 
    session                     Thread Cursor
 
412
    session                     Thread handler
122
413
    tables              Tables to drop
123
414
    if_exists           If set, don't give an error if table doesn't exists.
124
415
                        In this case we give an warning of level 'NOTE'
125
416
    drop_temporary      Only drop temporary tables
 
417
    drop_view           Allow to delete VIEW .frm
 
418
    dont_log_query      Don't write query to log files. This will also not
 
419
                        generate warnings if the handler files doesn't exists
126
420
 
127
 
  @todo
 
421
  TODO:
128
422
    When logging to the binary log, we should log
129
423
    tmp_tables and transactional tables as separate statements if we
130
424
    are in a transaction;  This is needed to get these tables into the
141
435
*/
142
436
 
143
437
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
144
 
                         bool drop_temporary)
 
438
                         bool drop_temporary, bool dont_log_query)
145
439
{
146
440
  TableList *table;
 
441
  char path[FN_REFLEN];
 
442
  uint32_t path_length= 0;
147
443
  String wrong_tables;
148
444
  int error= 0;
149
 
  bool foreign_key_error= false;
150
 
 
151
 
  {
152
 
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
153
 
 
154
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
 
    {
156
 
      table::Cache::singleton().mutex().unlock();
157
 
      return 1;
158
 
    }
159
 
 
160
 
    /* Don't give warnings for not found errors, as we already generate notes */
161
 
    session->no_warnings_for_error= 1;
162
 
 
163
 
    for (table= tables; table; table= table->next_local)
164
 
    {
165
 
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
166
 
 
167
 
      error= session->drop_temporary_table(tmp_identifier);
168
 
 
169
 
      switch (error) {
170
 
      case  0:
171
 
        // removed temporary table
172
 
        continue;
173
 
      case -1:
 
445
  int non_temp_tables_count= 0;
 
446
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
 
447
  String built_query;
 
448
 
 
449
  if (!dont_log_query)
 
450
  {
 
451
    built_query.set_charset(system_charset_info);
 
452
    if (if_exists)
 
453
      built_query.append("DROP Table IF EXISTS ");
 
454
    else
 
455
      built_query.append("DROP Table ");
 
456
  }
 
457
 
 
458
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
459
 
 
460
  /*
 
461
    If we have the table in the definition cache, we don't have to check the
 
462
    .frm file to find if the table is a normal table (not view) and what
 
463
    engine to use.
 
464
  */
 
465
 
 
466
  for (table= tables; table; table= table->next_local)
 
467
  {
 
468
    TableShare *share;
 
469
    table->db_type= NULL;
 
470
    if ((share= get_cached_table_share(table->db, table->table_name)))
 
471
      table->db_type= share->db_type();
 
472
  }
 
473
 
 
474
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
475
  {
 
476
    pthread_mutex_unlock(&LOCK_open);
 
477
    return 1;
 
478
  }
 
479
 
 
480
  /* Don't give warnings for not found errors, as we already generate notes */
 
481
  session->no_warnings_for_error= 1;
 
482
 
 
483
  for (table= tables; table; table= table->next_local)
 
484
  {
 
485
    char *db=table->db;
 
486
    StorageEngine *table_type;
 
487
 
 
488
    error= session->drop_temporary_table(table);
 
489
 
 
490
    switch (error) {
 
491
    case  0:
 
492
      // removed temporary table
 
493
      tmp_table_deleted= 1;
 
494
      continue;
 
495
    case -1:
 
496
      error= 1;
 
497
      goto err_with_placeholders;
 
498
    default:
 
499
      // temporary table not found
 
500
      error= 0;
 
501
    }
 
502
 
 
503
    /*
 
504
      If row-based replication is used and the table is not a
 
505
      temporary table, we add the table name to the drop statement
 
506
      being built.  The string always end in a comma and the comma
 
507
      will be chopped off before being written to the binary log.
 
508
      */
 
509
    if (!dont_log_query)
 
510
    {
 
511
      non_temp_tables_count++;
 
512
      /*
 
513
        Don't write the database name if it is the current one (or if
 
514
        session->db is NULL).
 
515
      */
 
516
      built_query.append("`");
 
517
      if (session->db == NULL || strcmp(db,session->db) != 0)
 
518
      {
 
519
        built_query.append(db);
 
520
        built_query.append("`.`");
 
521
      }
 
522
 
 
523
      built_query.append(table->table_name);
 
524
      built_query.append("`,");
 
525
    }
 
526
 
 
527
    table_type= table->db_type;
 
528
    if (!drop_temporary)
 
529
    {
 
530
      Table *locked_table;
 
531
      abort_locked_tables(session, db, table->table_name);
 
532
      remove_table_from_cache(session, db, table->table_name,
 
533
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
534
                              RTFC_CHECK_KILLED_FLAG);
 
535
      /*
 
536
        If the table was used in lock tables, remember it so that
 
537
        unlock_table_names can free it
 
538
      */
 
539
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
540
        table->table= locked_table;
 
541
 
 
542
      if (session->killed)
 
543
      {
 
544
        error= -1;
 
545
        goto err_with_placeholders;
 
546
      }
 
547
      /* remove .frm file and engine files */
 
548
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
 
549
    }
 
550
    if (drop_temporary ||
 
551
        ((table_type == NULL && (table_proto_exists(path)!=EEXIST))))
 
552
    {
 
553
      // Table was not found on disk and table can't be created from engine
 
554
      if (if_exists)
 
555
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
556
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
557
                            table->table_name);
 
558
      else
174
559
        error= 1;
175
 
        goto err_with_placeholders;
176
 
      default:
177
 
        // temporary table not found
178
 
        error= 0;
179
 
      }
180
 
 
181
 
      if (drop_temporary == false)
182
 
      {
183
 
        Table *locked_table;
184
 
        abort_locked_tables(session, tmp_identifier);
185
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
186
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
187
 
                                              RTFC_CHECK_KILLED_FLAG);
188
 
        /*
189
 
          If the table was used in lock tables, remember it so that
190
 
          unlock_table_names can free it
191
 
        */
192
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
193
 
          table->table= locked_table;
194
 
 
195
 
        if (session->getKilled())
196
 
        {
197
 
          error= -1;
198
 
          goto err_with_placeholders;
199
 
        }
200
 
      }
201
 
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
202
 
 
203
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
 
      {
205
 
        // Table was not found on disk and table can't be created from engine
206
 
        if (if_exists)
207
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
208
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
209
 
                              table->getTableName());
210
 
        else
211
 
          error= 1;
212
 
      }
213
 
      else
214
 
      {
215
 
        error= plugin::StorageEngine::dropTable(*session, identifier);
216
 
 
217
 
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
218
 
        {
219
 
          error= 0;
220
 
          session->clear_error();
221
 
        }
222
 
 
223
 
        if (error == HA_ERR_ROW_IS_REFERENCED)
224
 
        {
225
 
          /* the table is referenced by a foreign key constraint */
226
 
          foreign_key_error= true;
227
 
        }
228
 
      }
229
 
 
230
 
      if (error == 0 || (if_exists && foreign_key_error == false))
231
 
      {
232
 
        TransactionServices &transaction_services= TransactionServices::singleton();
233
 
        transaction_services.dropTable(session, string(table->getSchemaName()), string(table->getTableName()), if_exists);
234
 
      }
235
 
 
236
 
      if (error)
237
 
      {
238
 
        if (wrong_tables.length())
239
 
          wrong_tables.append(',');
240
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
241
 
      }
242
 
    }
243
 
    /*
244
 
      It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
245
 
      on the table name.
246
 
    */
247
 
    table::Cache::singleton().mutex().unlock();
 
560
    }
 
561
    else
 
562
    {
 
563
      error= ha_delete_table(session, path, db, table->table_name,
 
564
                             !dont_log_query);
 
565
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
 
566
          if_exists)
 
567
      {
 
568
        error= 0;
 
569
        session->clear_error();
 
570
      }
 
571
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
572
      {
 
573
        /* the table is referenced by a foreign key constraint */
 
574
        foreign_key_error=1;
 
575
      }
 
576
      if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
 
577
      {
 
578
        int new_error;
 
579
 
 
580
        if (!(new_error= delete_table_proto_file(path)))
 
581
        {
 
582
          some_tables_deleted=1;
 
583
          new_error= 0;
 
584
        }
 
585
        error|= new_error;
 
586
      }
 
587
    }
 
588
    if (error)
 
589
    {
 
590
      if (wrong_tables.length())
 
591
        wrong_tables.append(',');
 
592
      wrong_tables.append(String(table->table_name,system_charset_info));
 
593
    }
248
594
  }
 
595
  /*
 
596
    It's safe to unlock LOCK_open: we have an exclusive lock
 
597
    on the table name.
 
598
  */
 
599
  pthread_mutex_unlock(&LOCK_open);
249
600
  error= 0;
250
 
 
251
601
  if (wrong_tables.length())
252
602
  {
253
 
    if (not foreign_key_error)
254
 
    {
 
603
    if (!foreign_key_error)
255
604
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
605
                      wrong_tables.c_ptr());
257
 
    }
258
606
    else
259
607
    {
260
608
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
262
610
    error= 1;
263
611
  }
264
612
 
265
 
  table::Cache::singleton().mutex().lock(); /* final bit in rm table lock */
 
613
  if (some_tables_deleted || tmp_table_deleted || !error)
 
614
  {
 
615
    if (!dont_log_query)
 
616
    {
 
617
      if ((non_temp_tables_count > 0 && !tmp_table_deleted))
 
618
      {
 
619
        /*
 
620
          In this case, we are either using statement-based
 
621
          replication or using row-based replication but have only
 
622
          deleted one or more non-temporary tables (and no temporary
 
623
          tables).  In this case, we can write the original query into
 
624
          the binary log.
 
625
         */
 
626
        write_bin_log(session, !error, session->query, session->query_length);
 
627
      }
 
628
      else if (non_temp_tables_count > 0 &&
 
629
               tmp_table_deleted)
 
630
      {
 
631
        /*
 
632
          In this case we have deleted both temporary and
 
633
          non-temporary tables, so:
 
634
          - since we have deleted a non-temporary table we have to
 
635
            binlog the statement, but
 
636
          - since we have deleted a temporary table we cannot binlog
 
637
            the statement (since the table has not been created on the
 
638
            slave, this might cause the slave to stop).
266
639
 
 
640
          Instead, we write a built statement, only containing the
 
641
          non-temporary tables, to the binary log
 
642
        */
 
643
        built_query.chop();                  // Chop of the last comma
 
644
        built_query.append(" /* generated by server */");
 
645
        write_bin_log(session, !error, built_query.ptr(), built_query.length());
 
646
      }
 
647
      /*
 
648
        The remaining cases are:
 
649
        - no tables where deleted and
 
650
        - only temporary tables where deleted and row-based
 
651
          replication is used.
 
652
        In both these cases, nothing should be written to the binary
 
653
        log.
 
654
      */
 
655
    }
 
656
  }
 
657
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
267
658
err_with_placeholders:
268
 
  tables->unlock_table_names();
269
 
  table::Cache::singleton().mutex().unlock();
 
659
  unlock_table_names(tables, NULL);
 
660
  pthread_mutex_unlock(&LOCK_open);
270
661
  session->no_warnings_for_error= 0;
271
662
 
272
 
  return error;
 
663
  return(error);
 
664
}
 
665
 
 
666
 
 
667
/*
 
668
  Quickly remove a table.
 
669
 
 
670
  SYNOPSIS
 
671
    quick_rm_table()
 
672
      base                      The StorageEngine handle.
 
673
      db                        The database name.
 
674
      table_name                The table name.
 
675
      is_tmp                    If the table is temp.
 
676
 
 
677
  RETURN
 
678
    0           OK
 
679
    != 0        Error
 
680
*/
 
681
 
 
682
bool quick_rm_table(StorageEngine *, const char *db,
 
683
                    const char *table_name, bool is_tmp)
 
684
{
 
685
  char path[FN_REFLEN];
 
686
  bool error= 0;
 
687
 
 
688
  build_table_filename(path, sizeof(path), db, table_name, is_tmp);
 
689
 
 
690
  error= delete_table_proto_file(path);
 
691
 
 
692
  return(ha_delete_table(current_session, path, db, table_name, 0) ||
 
693
              error);
273
694
}
274
695
 
275
696
/*
285
706
  PRIMARY keys are prioritized.
286
707
*/
287
708
 
288
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
709
static int sort_keys(KEY *a, KEY *b)
289
710
{
290
711
  ulong a_flags= a->flags, b_flags= b->flags;
291
712
 
337
758
    1             Error
338
759
*/
339
760
 
340
 
class typelib_set_member
341
 
{
342
 
public:
343
 
  string s;
344
 
  const CHARSET_INFO * const cs;
345
 
 
346
 
  typelib_set_member(const char* value, unsigned int length,
347
 
                     const CHARSET_INFO * const charset)
348
 
    : s(value, length),
349
 
      cs(charset)
350
 
  {}
351
 
};
352
 
 
353
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
354
 
{
355
 
  return (my_strnncoll(a.cs,
356
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
357
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
358
 
}
359
 
 
360
 
 
361
 
namespace
362
 
{
363
 
class typelib_set_member_hasher
364
 
{
365
 
  boost::hash<string> hasher;
366
 
public:
367
 
  std::size_t operator()(const typelib_set_member& t) const
368
 
  {
369
 
    return hasher(t.s);
370
 
  }
371
 
};
372
 
}
373
 
 
374
 
static bool check_duplicates_in_interval(const char *set_or_name,
375
 
                                         const char *name, TYPELIB *typelib,
376
 
                                         const CHARSET_INFO * const cs,
377
 
                                         unsigned int *dup_val_count)
 
761
bool check_duplicates_in_interval(const char *set_or_name,
 
762
                                  const char *name, TYPELIB *typelib,
 
763
                                  const CHARSET_INFO * const cs, unsigned int *dup_val_count)
378
764
{
379
765
  TYPELIB tmp= *typelib;
380
766
  const char **cur_value= typelib->type_names;
381
767
  unsigned int *cur_length= typelib->type_lengths;
382
768
  *dup_val_count= 0;
383
769
 
384
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
385
 
 
386
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
770
  for ( ; tmp.count > 1; cur_value++, cur_length++)
387
771
  {
388
772
    tmp.type_names++;
389
773
    tmp.type_lengths++;
390
774
    tmp.count--;
391
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
775
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
392
776
    {
393
777
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
394
778
               name,*cur_value,set_or_name);
395
779
      return 1;
396
780
    }
397
 
    else
398
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
399
781
  }
400
782
  return 0;
401
783
}
419
801
  RETURN VALUES
420
802
    void
421
803
*/
422
 
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
423
 
                                       TYPELIB *interval,
424
 
                                       uint32_t *max_length,
425
 
                                       uint32_t *tot_length)
 
804
void calculate_interval_lengths(const CHARSET_INFO * const cs, TYPELIB *interval,
 
805
                                uint32_t *max_length, uint32_t *tot_length)
426
806
{
427
807
  const char **pos;
428
808
  uint32_t *len;
436
816
  }
437
817
}
438
818
 
 
819
 
439
820
/*
440
821
  Prepare a create_table instance for packing
441
822
 
444
825
    sql_field     field to prepare for packing
445
826
    blob_columns  count for BLOBs
446
827
    timestamps    count for timestamps
 
828
    table_flags   table flags
447
829
 
448
830
  DESCRIPTION
449
831
    This function prepares a CreateField instance.
453
835
   0    ok
454
836
   1    Error
455
837
*/
 
838
 
456
839
int prepare_create_field(CreateField *sql_field,
457
840
                         uint32_t *blob_columns,
458
 
                         int *timestamps,
459
 
                         int *timestamps_with_niladic)
 
841
                         int *timestamps, int *timestamps_with_niladic,
 
842
                         int64_t )
460
843
{
461
844
  unsigned int dup_val_count;
462
845
 
468
851
 
469
852
  switch (sql_field->sql_type) {
470
853
  case DRIZZLE_TYPE_BLOB:
471
 
    sql_field->length= 8; // Unireg field length
 
854
    sql_field->pack_flag=FIELDFLAG_BLOB |
 
855
      pack_length_to_packflag(sql_field->pack_length -
 
856
                              portable_sizeof_char_ptr);
 
857
    if (sql_field->charset->state & MY_CS_BINSORT)
 
858
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
859
    sql_field->length=8;                        // Unireg field length
472
860
    (*blob_columns)++;
473
861
    break;
474
862
  case DRIZZLE_TYPE_VARCHAR:
 
863
    sql_field->pack_flag=0;
 
864
    if (sql_field->charset->state & MY_CS_BINSORT)
 
865
      sql_field->pack_flag|=FIELDFLAG_BINARY;
475
866
    break;
476
867
  case DRIZZLE_TYPE_ENUM:
477
 
    if (check_duplicates_in_interval("ENUM",
478
 
                                     sql_field->field_name,
479
 
                                     sql_field->interval,
480
 
                                     sql_field->charset,
481
 
                                     &dup_val_count))
 
868
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
869
      FIELDFLAG_INTERVAL;
 
870
    if (sql_field->charset->state & MY_CS_BINSORT)
 
871
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
872
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
 
873
                                 sql_field->interval,
 
874
                                     sql_field->charset, &dup_val_count))
482
875
      return 1;
483
876
    break;
484
877
  case DRIZZLE_TYPE_DATE:  // Rest of string types
485
878
  case DRIZZLE_TYPE_DATETIME:
486
879
  case DRIZZLE_TYPE_NULL:
 
880
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
487
881
    break;
488
 
  case DRIZZLE_TYPE_DECIMAL:
 
882
  case DRIZZLE_TYPE_NEWDECIMAL:
 
883
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
884
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
885
                           FIELDFLAG_DECIMAL) |
 
886
                          (sql_field->flags & DECIMAL_FLAG ?  FIELDFLAG_DECIMAL_POSITION : 0) |
 
887
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
489
888
    break;
490
889
  case DRIZZLE_TYPE_TIMESTAMP:
491
890
    /* We should replace old TIMESTAMP fields with their newer analogs */
497
896
        (*timestamps_with_niladic)++;
498
897
      }
499
898
      else
500
 
      {
501
899
        sql_field->unireg_check= Field::NONE;
502
 
      }
503
900
    }
504
901
    else if (sql_field->unireg_check != Field::NONE)
505
902
      (*timestamps_with_niladic)++;
507
904
    (*timestamps)++;
508
905
    /* fall-through */
509
906
  default:
 
907
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
908
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
909
                           FIELDFLAG_DECIMAL) |
 
910
                          f_settype((uint32_t) sql_field->sql_type) |
 
911
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
510
912
    break;
511
913
  }
512
 
 
 
914
  if (!(sql_field->flags & NOT_NULL_FLAG))
 
915
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
 
916
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
 
917
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
513
918
  return 0;
514
919
}
515
920
 
516
 
static int mysql_prepare_create_table(Session *session,
517
 
                                      HA_CREATE_INFO *create_info,
518
 
                                      message::Table &create_proto,
519
 
                                      AlterInfo *alter_info,
520
 
                                      bool tmp_table,
521
 
                                      uint32_t *db_options,
522
 
                                      KeyInfo **key_info_buffer,
523
 
                                      uint32_t *key_count,
524
 
                                      int select_field_count)
 
921
/*
 
922
  Preparation for table creation
 
923
 
 
924
  SYNOPSIS
 
925
    mysql_prepare_create_table()
 
926
      session                       Thread object.
 
927
      create_info               Create information (like MAX_ROWS).
 
928
      alter_info                List of columns and indexes to create
 
929
      tmp_table                 If a temporary table is to be created.
 
930
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
 
931
      file                      The handler for the new table.
 
932
      key_info_buffer     OUT   An array of KEY structs for the indexes.
 
933
      key_count           OUT   The number of elements in the array.
 
934
      select_field_count        The number of fields coming from a select table.
 
935
 
 
936
  DESCRIPTION
 
937
    Prepares the table and key structures for table creation.
 
938
 
 
939
  NOTES
 
940
    sets create_info->varchar if the table has a varchar
 
941
 
 
942
  RETURN VALUES
 
943
    false    OK
 
944
    true     error
 
945
*/
 
946
 
 
947
static int
 
948
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
 
949
                           Alter_info *alter_info,
 
950
                           bool tmp_table,
 
951
                               uint32_t *db_options,
 
952
                               handler *file, KEY **key_info_buffer,
 
953
                               uint32_t *key_count, int select_field_count)
525
954
{
526
955
  const char    *key_name;
527
956
  CreateField   *sql_field,*dup_field;
528
957
  uint          field,null_fields,blob_columns,max_key_length;
529
958
  ulong         record_offset= 0;
530
 
  KeyInfo               *key_info;
531
 
  KeyPartInfo *key_part_info;
 
959
  KEY           *key_info;
 
960
  KEY_PART_INFO *key_part_info;
532
961
  int           timestamps= 0, timestamps_with_niladic= 0;
533
962
  int           field_no,dup_no;
534
963
  int           select_field_pos,auto_increment=0;
536
965
  List_iterator<CreateField> it2(alter_info->create_list);
537
966
  uint32_t total_uneven_bit_length= 0;
538
967
 
539
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
540
 
 
541
968
  select_field_pos= alter_info->create_list.elements - select_field_count;
542
969
  null_fields=blob_columns=0;
543
 
  max_key_length= engine->max_key_length();
 
970
  create_info->varchar= 0;
 
971
  max_key_length= file->max_key_length();
544
972
 
545
973
  for (field_no=0; (sql_field=it++) ; field_no++)
546
974
  {
606
1034
 
607
1035
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
608
1036
    {
609
 
      size_t dummy;
 
1037
      uint32_t dummy;
610
1038
      const CHARSET_INFO * const cs= sql_field->charset;
611
1039
      TYPELIB *interval= sql_field->interval;
612
1040
 
624
1052
        */
625
1053
        interval= sql_field->interval= typelib(session->mem_root,
626
1054
                                               sql_field->interval_list);
627
 
 
628
 
        List_iterator<String> int_it(sql_field->interval_list);
629
 
        String conv, *tmp;
 
1055
        String conv;
630
1056
        char comma_buf[4];
631
1057
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
632
1058
                                          (unsigned char*) comma_buf +
633
1059
                                          sizeof(comma_buf));
634
1060
        assert(comma_length > 0);
635
1061
 
636
 
        for (uint32_t i= 0; (tmp= int_it++); i++)
 
1062
        vector<String*>::iterator int_it= sql_field->interval_list.begin();
 
1063
        for (uint32_t i= 0; int_it != sql_field->interval_list.end(); ++int_it, ++i)
637
1064
        {
638
 
          uint32_t lengthsp;
 
1065
          String *tmp= *int_it;
639
1066
          if (String::needs_conversion(tmp->length(), tmp->charset(),
640
1067
                                       cs, &dummy))
641
1068
          {
642
 
            size_t cnv_errs;
 
1069
            uint32_t cnv_errs;
643
1070
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
644
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
1071
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
1072
                                                  conv.length());
645
1073
            interval->type_lengths[i]= conv.length();
646
1074
          }
647
1075
 
648
1076
          // Strip trailing spaces.
649
 
          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
650
 
                                       interval->type_lengths[i]);
 
1077
          uint32_t lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
 
1078
                                                interval->type_lengths[i]);
651
1079
          interval->type_lengths[i]= lengthsp;
652
1080
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
653
1081
        }
681
1109
            }
682
1110
          }
683
1111
        }
684
 
        uint32_t new_dummy;
685
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
1112
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
686
1113
        sql_field->length= field_length;
687
1114
      }
688
1115
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
746
1173
        }
747
1174
      }
748
1175
    }
749
 
 
750
 
    /** @todo Get rid of this MyISAM-specific crap. */
751
 
    if (not create_proto.engine().name().compare("MyISAM") &&
752
 
        ((sql_field->flags & BLOB_FLAG) ||
753
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
 
1176
    /* Don't pack rows in old tables if the user has requested this */
 
1177
    if ((sql_field->flags & BLOB_FLAG) ||
 
1178
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
754
1179
      (*db_options)|= HA_OPTION_PACK_RECORD;
755
1180
    it2.rewind();
756
1181
  }
765
1190
    assert(sql_field->charset != 0);
766
1191
 
767
1192
    if (prepare_create_field(sql_field, &blob_columns,
768
 
                             &timestamps, &timestamps_with_niladic))
 
1193
                             &timestamps, &timestamps_with_niladic,
 
1194
                             file->ha_table_flags()))
769
1195
      return(true);
 
1196
    if (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
 
1197
      create_info->varchar= true;
770
1198
    sql_field->offset= record_offset;
771
1199
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
772
1200
      auto_increment++;
783
1211
    return(true);
784
1212
  }
785
1213
  if (auto_increment &&
786
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1214
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
787
1215
  {
788
1216
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
789
1217
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
790
1218
    return(true);
791
1219
  }
792
1220
 
793
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1221
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
794
1222
  {
795
1223
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
796
1224
               MYF(0));
818
1246
      fk_key_count++;
819
1247
      if (((Foreign_key *)key)->validate(alter_info->create_list))
820
1248
        return true;
821
 
 
822
1249
      Foreign_key *fk_key= (Foreign_key*) key;
823
 
 
824
 
      add_foreign_key_to_table_message(&create_proto,
825
 
                                       fk_key->name.str,
826
 
                                       fk_key->columns,
827
 
                                       fk_key->ref_table,
828
 
                                       fk_key->ref_columns,
829
 
                                       fk_key->delete_opt,
830
 
                                       fk_key->update_opt,
831
 
                                       fk_key->match_opt);
832
 
 
833
1250
      if (fk_key->ref_columns.elements &&
834
1251
          fk_key->ref_columns.elements != fk_key->columns.elements)
835
1252
      {
842
1259
      continue;
843
1260
    }
844
1261
    (*key_count)++;
845
 
    tmp= engine->max_key_parts();
 
1262
    tmp=file->max_key_parts();
846
1263
    if (key->columns.elements > tmp)
847
1264
    {
848
1265
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
864
1281
             key2->name.str != ignore_key &&
865
1282
             !foreign_key_prefix(key, key2)))
866
1283
        {
867
 
          /* @todo issue warning message */
 
1284
          /* TODO: issue warning message */
868
1285
          /* mark that the generated key should be ignored */
869
1286
          if (!key2->generated ||
870
1287
              (key->generated && key->columns.elements <
891
1308
      return(true);
892
1309
    }
893
1310
  }
894
 
  tmp= engine->max_keys();
 
1311
  tmp=file->max_keys();
895
1312
  if (*key_count > tmp)
896
1313
  {
897
1314
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
898
1315
    return(true);
899
1316
  }
900
1317
 
901
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
902
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
1318
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1319
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
903
1320
  if (!*key_info_buffer || ! key_part_info)
904
1321
    return(true);                               // Out of memory
905
1322
 
939
1356
    key_info->usable_key_parts= key_number;
940
1357
    key_info->algorithm= key->key_create_info.algorithm;
941
1358
 
 
1359
    /* Take block size from key part or table part */
 
1360
    /*
 
1361
      TODO: Add warning if block size changes. We can't do it here, as
 
1362
      this may depend on the size of the key
 
1363
    */
 
1364
    key_info->block_size= (key->key_create_info.block_size ?
 
1365
                           key->key_create_info.block_size :
 
1366
                           create_info->key_block_size);
 
1367
 
 
1368
    if (key_info->block_size)
 
1369
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
1370
 
942
1371
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
943
1372
                                           key->key_create_info.comment.str,
944
1373
                                           key->key_create_info.comment.str +
960
1389
      key_info->comment.str= key->key_create_info.comment.str;
961
1390
    }
962
1391
 
963
 
    message::Table::Field *protofield= NULL;
964
 
 
965
1392
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
966
1393
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
967
1394
    {
968
1395
      uint32_t length;
969
1396
      Key_part_spec *dup_column;
970
 
      int proto_field_nr= 0;
971
1397
 
972
1398
      it.rewind();
973
1399
      field=0;
974
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
1400
      while ((sql_field=it++) &&
975
1401
             my_strcasecmp(system_charset_info,
976
1402
                           column->field_name.str,
977
1403
                           sql_field->field_name))
984
1410
      while ((dup_column= cols2++) != column)
985
1411
      {
986
1412
        if (!my_strcasecmp(system_charset_info,
987
 
                           column->field_name.str, dup_column->field_name.str))
 
1413
                           column->field_name.str, dup_column->field_name.str))
988
1414
        {
989
1415
          my_printf_error(ER_DUP_FIELDNAME,
990
1416
                          ER(ER_DUP_FIELDNAME),MYF(0),
993
1419
        }
994
1420
      }
995
1421
      cols2.rewind();
996
 
 
997
 
      if (create_proto.field_size() > 0)
998
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
999
 
 
1000
1422
      {
1001
 
        column->length*= sql_field->charset->mbmaxlen;
 
1423
        column->length*= sql_field->charset->mbmaxlen;
1002
1424
 
1003
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1004
 
        {
1005
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1006
 
          {
1007
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1008
 
            return true;
1009
 
          }
1010
 
          if (! column->length)
1011
 
          {
1012
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
1013
 
            return true;
1014
 
          }
1015
 
        }
1016
 
        if (! (sql_field->flags & NOT_NULL_FLAG))
1017
 
        {
1018
 
          if (key->type == Key::PRIMARY)
1019
 
          {
1020
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1021
 
            sql_field->flags|= NOT_NULL_FLAG;
 
1425
        if (f_is_blob(sql_field->pack_flag))
 
1426
        {
 
1427
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
1428
          {
 
1429
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
1430
            return(true);
 
1431
          }
 
1432
          if (!column->length)
 
1433
          {
 
1434
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
1435
            return(true);
 
1436
          }
 
1437
        }
 
1438
        if (!(sql_field->flags & NOT_NULL_FLAG))
 
1439
        {
 
1440
          if (key->type == Key::PRIMARY)
 
1441
          {
 
1442
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
1443
            sql_field->flags|= NOT_NULL_FLAG;
 
1444
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1022
1445
            null_fields--;
1023
 
 
1024
 
            if (protofield)
1025
 
            {
1026
 
              message::Table::Field::FieldConstraints *constraints;
1027
 
              constraints= protofield->mutable_constraints();
1028
 
              constraints->set_is_nullable(false);
1029
 
            }
1030
 
 
1031
 
          }
1032
 
          else
 
1446
          }
 
1447
          else
1033
1448
          {
1034
1449
            key_info->flags|= HA_NULL_PART_KEY;
1035
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1450
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1036
1451
            {
1037
1452
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1038
 
              return true;
 
1453
              return(true);
1039
1454
            }
1040
1455
          }
1041
 
        }
1042
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1043
 
        {
1044
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1045
 
            auto_increment--;                   // Field is used
1046
 
        }
 
1456
        }
 
1457
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
1458
        {
 
1459
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
 
1460
            auto_increment--;                   // Field is used
 
1461
        }
1047
1462
      }
1048
1463
 
1049
1464
      key_part_info->fieldnr= field;
1050
1465
      key_part_info->offset=  (uint16_t) sql_field->offset;
1051
 
      key_part_info->key_type= 0;
 
1466
      key_part_info->key_type=sql_field->pack_flag;
1052
1467
      length= sql_field->key_length;
1053
1468
 
1054
1469
      if (column->length)
1055
1470
      {
1056
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
1471
        if (f_is_blob(sql_field->pack_flag))
1057
1472
        {
1058
1473
          if ((length=column->length) > max_key_length ||
1059
 
              length > engine->max_key_part_length())
 
1474
              length > file->max_key_part_length())
1060
1475
          {
1061
 
            length= min(max_key_length, engine->max_key_part_length());
 
1476
            length= min(max_key_length, file->max_key_part_length());
1062
1477
            if (key->type == Key::MULTIPLE)
1063
1478
            {
1064
1479
              /* not a critical problem */
1078
1493
          }
1079
1494
        }
1080
1495
        else if ((column->length > length ||
1081
 
            ! Field::type_can_have_key_part(sql_field->sql_type)))
 
1496
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
 
1497
                   ((f_is_packed(sql_field->pack_flag) ||
 
1498
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
 
1499
                      (key_info->flags & HA_NOSAME))) &&
 
1500
                    column->length != length)))
1082
1501
        {
1083
1502
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1084
1503
          return(true);
1085
1504
        }
1086
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1087
 
        {
 
1505
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1088
1506
          length=column->length;
1089
 
        }
1090
1507
      }
1091
1508
      else if (length == 0)
1092
1509
      {
1093
1510
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1094
1511
          return(true);
1095
1512
      }
1096
 
      if (length > engine->max_key_part_length())
 
1513
      if (length > file->max_key_part_length())
1097
1514
      {
1098
 
        length= engine->max_key_part_length();
 
1515
        length= file->max_key_part_length();
1099
1516
        if (key->type == Key::MULTIPLE)
1100
1517
        {
1101
1518
          /* not a critical problem */
1116
1533
      key_part_info->length=(uint16_t) length;
1117
1534
      /* Use packed keys for long strings on the first column */
1118
1535
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1119
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1120
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1121
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1536
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1537
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1538
            sql_field->pack_flag & FIELDFLAG_BLOB)))
1122
1539
      {
1123
 
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
 
1540
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1124
1541
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1125
 
        {
1126
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1127
 
        }
1128
 
        else
1129
 
        {
1130
 
          key_info->flags|= HA_PACK_KEY;
1131
 
        }
 
1542
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
1543
        else
 
1544
          key_info->flags|= HA_PACK_KEY;
1132
1545
      }
1133
1546
      /* Check if the key segment is partial, set the key flag accordingly */
1134
1547
      if (length != sql_field->key_length)
1179
1592
    key_info++;
1180
1593
  }
1181
1594
  if (!unique_key && !primary_key &&
1182
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1595
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1183
1596
  {
1184
1597
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1185
1598
    return(true);
1190
1603
    return(true);
1191
1604
  }
1192
1605
  /* Sort keys in optimized order */
1193
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1194
 
                     (qsort_cmp) sort_keys);
 
1606
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1607
           (qsort_cmp) sort_keys);
 
1608
  create_info->null_bits= null_fields;
1195
1609
 
1196
1610
  /* Check fields. */
1197
1611
  it.rewind();
1264
1678
  return 0;
1265
1679
}
1266
1680
 
1267
 
static bool locked_create_event(Session *session,
1268
 
                                const TableIdentifier &identifier,
1269
 
                                HA_CREATE_INFO *create_info,
1270
 
                                message::Table &table_proto,
1271
 
                                AlterInfo *alter_info,
1272
 
                                bool is_if_not_exists,
1273
 
                                bool internal_tmp_table,
1274
 
                                uint db_options,
1275
 
                                uint key_count,
1276
 
                                KeyInfo *key_info_buffer)
1277
 
{
1278
 
  bool error= true;
1279
 
 
1280
 
  {
1281
 
 
1282
 
    /*
1283
 
      @note if we are building a temp table we need to check to see if a temp table
1284
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1285
 
      to create a table under a temporary table.
1286
 
    */
1287
 
    bool exists= 
1288
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1289
 
                                            identifier.getType() != message::Table::STANDARD );
1290
 
 
1291
 
    if (exists)
1292
 
    {
1293
 
      if (is_if_not_exists)
1294
 
      {
1295
 
        error= false;
1296
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1297
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1298
 
                            identifier.getTableName().c_str());
1299
 
        create_info->table_existed= 1;          // Mark that table existed
1300
 
        return error;
1301
 
      }
1302
 
 
1303
 
      std::string path;
1304
 
      identifier.getSQLPath(path);
1305
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1306
 
 
1307
 
      return error;
1308
 
    }
1309
 
 
1310
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1311
 
    {
1312
 
      /*
1313
 
        We don't assert here, but check the result, because the table could be
1314
 
        in the table definition cache and in the same time the .frm could be
1315
 
        missing from the disk, in case of manual intervention which deletes
1316
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1317
 
        Then she could create the table. This case is pretty obscure and
1318
 
        therefore we don't introduce a new error message only for it.
1319
 
      */
1320
 
      /*
1321
 
        @todo improve this error condition.
1322
 
      */
1323
 
      if (definition::Cache::singleton().find(identifier.getKey()))
1324
 
      {
1325
 
        std::string path;
1326
 
        identifier.getSQLPath(path);
1327
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1328
 
 
1329
 
        return error;
1330
 
      }
1331
 
    }
1332
 
  }
1333
 
 
1334
 
  session->set_proc_info("creating table");
1335
 
  create_info->table_existed= 0;                // Mark that table is created
1336
 
 
1337
 
  create_info->table_options= db_options;
1338
 
 
1339
 
  if (not rea_create_table(session, identifier,
1340
 
                           table_proto,
1341
 
                           create_info, alter_info->create_list,
1342
 
                           key_count, key_info_buffer))
1343
 
  {
1344
 
    return error;
1345
 
  }
1346
 
 
1347
 
  if (identifier.getType() == message::Table::TEMPORARY)
1348
 
  {
1349
 
    /* Open table and put in temporary table list */
1350
 
    if (not (session->open_temporary_table(identifier)))
1351
 
    {
1352
 
      (void) session->rm_temporary_table(identifier);
1353
 
      return error;
1354
 
    }
1355
 
  }
1356
 
 
1357
 
  /* 
1358
 
    We keep this behind the lock to make sure ordering is correct for a table.
1359
 
    This is a very unlikely problem where before we would write out to the
1360
 
    trans log, someone would do a delete/create operation.
1361
 
  */
1362
 
 
1363
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1364
 
  {
1365
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1366
 
    transaction_services.createTable(session, table_proto);
1367
 
  }
1368
 
 
1369
 
  return false;
1370
 
}
1371
 
 
1372
1681
 
1373
1682
/*
1374
1683
  Ignore the name of this function... it locks :(
1401
1710
*/
1402
1711
 
1403
1712
bool mysql_create_table_no_lock(Session *session,
1404
 
                                const TableIdentifier &identifier,
 
1713
                                const char *db, const char *table_name,
1405
1714
                                HA_CREATE_INFO *create_info,
1406
 
                                message::Table &table_proto,
1407
 
                                AlterInfo *alter_info,
 
1715
                                drizzled::message::Table *table_proto,
 
1716
                                Alter_info *alter_info,
1408
1717
                                bool internal_tmp_table,
1409
 
                                uint32_t select_field_count,
1410
 
                                bool is_if_not_exists)
 
1718
                                uint32_t select_field_count)
1411
1719
{
 
1720
  char          path[FN_REFLEN];
 
1721
  uint32_t          path_length;
1412
1722
  uint          db_options, key_count;
1413
 
  KeyInfo               *key_info_buffer;
 
1723
  KEY           *key_info_buffer;
 
1724
  handler       *file;
1414
1725
  bool          error= true;
1415
 
 
1416
1726
  /* Check for duplicate fields and check type of table to create */
1417
 
  if (not alter_info->create_list.elements)
 
1727
  if (!alter_info->create_list.elements)
1418
1728
  {
1419
1729
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1420
1730
               MYF(0));
1421
1731
    return true;
1422
1732
  }
1423
 
  assert(identifier.getTableName() == table_proto.name());
 
1733
  assert(strcmp(table_name,table_proto->name().c_str())==0);
 
1734
  if (check_engine(session, table_name, create_info))
 
1735
    return true;
1424
1736
  db_options= create_info->table_options;
1425
 
 
1426
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1427
 
 
1428
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1429
 
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1430
 
                                     internal_tmp_table,
1431
 
                                     &db_options,
1432
 
                                     &key_info_buffer, &key_count,
1433
 
                                     select_field_count))
1434
 
  {
1435
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1436
 
    error= locked_create_event(session,
1437
 
                               identifier,
1438
 
                               create_info,
1439
 
                               table_proto,
1440
 
                               alter_info,
1441
 
                               is_if_not_exists,
1442
 
                               internal_tmp_table,
1443
 
                               db_options, key_count,
1444
 
                               key_info_buffer);
1445
 
  }
1446
 
 
 
1737
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1738
    db_options|=HA_OPTION_PACK_RECORD;
 
1739
  if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
 
1740
                              create_info->db_type)))
 
1741
  {
 
1742
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
1743
    return true;
 
1744
  }
 
1745
 
 
1746
  set_table_default_charset(create_info, (char*) db);
 
1747
 
 
1748
  if (mysql_prepare_create_table(session, create_info, alter_info,
 
1749
                                 internal_tmp_table,
 
1750
                                 &db_options, file,
 
1751
                                 &key_info_buffer, &key_count,
 
1752
                                 select_field_count))
 
1753
    goto err;
 
1754
 
 
1755
      /* Check if table exists */
 
1756
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1757
  {
 
1758
    path_length= build_tmptable_filename(session, path, sizeof(path));
 
1759
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
1760
  }
 
1761
  else
 
1762
  {
 
1763
 #ifdef FN_DEVCHAR
 
1764
    /* check if the table name contains FN_DEVCHAR when defined */
 
1765
    if (strchr(table_name, FN_DEVCHAR))
 
1766
    {
 
1767
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
 
1768
      return true;
 
1769
    }
 
1770
#endif
 
1771
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
 
1772
  }
 
1773
 
 
1774
  /* Check if table already exists */
 
1775
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1776
      session->find_temporary_table(db, table_name))
 
1777
  {
 
1778
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1779
    {
 
1780
      create_info->table_existed= 1;            // Mark that table existed
 
1781
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1782
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1783
                          table_name);
 
1784
      error= 0;
 
1785
      goto err;
 
1786
    }
 
1787
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1788
    goto err;
 
1789
  }
 
1790
 
 
1791
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1792
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1793
  {
 
1794
    if (table_proto_exists(path)==EEXIST)
 
1795
    {
 
1796
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1797
      {
 
1798
        error= false;
 
1799
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1800
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1801
                            table_name);
 
1802
        create_info->table_existed= 1;          // Mark that table existed
 
1803
      }
 
1804
      else 
 
1805
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1806
 
 
1807
      goto unlock_and_end;
 
1808
    }
 
1809
    /*
 
1810
      We don't assert here, but check the result, because the table could be
 
1811
      in the table definition cache and in the same time the .frm could be
 
1812
      missing from the disk, in case of manual intervention which deletes
 
1813
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1814
      Then she could create the table. This case is pretty obscure and
 
1815
      therefore we don't introduce a new error message only for it.
 
1816
    */
 
1817
    if (get_cached_table_share(db, table_name))
 
1818
    {
 
1819
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1820
      goto unlock_and_end;
 
1821
    }
 
1822
  }
 
1823
 
 
1824
  /*
 
1825
    Check that table with given name does not already
 
1826
    exist in any storage engine. In such a case it should
 
1827
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1828
    unless user specified CREATE TABLE IF EXISTS
 
1829
    The LOCK_open mutex has been locked to make sure no
 
1830
    one else is attempting to discover the table. Since
 
1831
    it's not on disk as a frm file, no one could be using it!
 
1832
  */
 
1833
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1834
  {
 
1835
    bool create_if_not_exists =
 
1836
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1837
    int retcode = ha_table_exists_in_engine(session, db, table_name);
 
1838
    switch (retcode)
 
1839
    {
 
1840
      case HA_ERR_NO_SUCH_TABLE:
 
1841
        /* Normal case, no table exists. we can go and create it */
 
1842
        break;
 
1843
      case HA_ERR_TABLE_EXIST:
 
1844
        if (create_if_not_exists)
 
1845
        {
 
1846
          error= false;
 
1847
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1848
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1849
                              table_name);
 
1850
          create_info->table_existed= 1;                // Mark that table existed
 
1851
          goto unlock_and_end;
 
1852
        }
 
1853
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1854
        goto unlock_and_end;
 
1855
      default:
 
1856
        my_error(retcode, MYF(0),table_name);
 
1857
        goto unlock_and_end;
 
1858
    }
 
1859
  }
 
1860
 
 
1861
  session->set_proc_info("creating table");
 
1862
  create_info->table_existed= 0;                // Mark that table is created
 
1863
 
 
1864
#ifdef HAVE_READLINK
 
1865
  if (test_if_data_home_dir(create_info->data_file_name))
 
1866
  {
 
1867
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
 
1868
    goto unlock_and_end;
 
1869
  }
 
1870
  if (test_if_data_home_dir(create_info->index_file_name))
 
1871
  {
 
1872
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
 
1873
    goto unlock_and_end;
 
1874
  }
 
1875
 
 
1876
  if (!my_use_symdir)
 
1877
#endif /* HAVE_READLINK */
 
1878
  {
 
1879
    if (create_info->data_file_name)
 
1880
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1881
                   "DATA DIRECTORY option ignored");
 
1882
    if (create_info->index_file_name)
 
1883
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
 
1884
                   "INDEX DIRECTORY option ignored");
 
1885
    create_info->data_file_name= create_info->index_file_name= 0;
 
1886
  }
 
1887
  create_info->table_options=db_options;
 
1888
 
 
1889
  if (rea_create_table(session, path, db, table_name,
 
1890
                       table_proto,
 
1891
                       create_info, alter_info->create_list,
 
1892
                       key_count, key_info_buffer, false))
 
1893
    goto unlock_and_end;
 
1894
 
 
1895
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1896
  {
 
1897
    /* Open table and put in temporary table list */
 
1898
    if (!(open_temporary_table(session, path, db, table_name, 1, OTM_OPEN)))
 
1899
    {
 
1900
      (void) rm_temporary_table(create_info->db_type, path);
 
1901
      goto unlock_and_end;
 
1902
    }
 
1903
  }
 
1904
 
 
1905
  /*
 
1906
    Don't write statement if:
 
1907
    - It is an internal temporary table,
 
1908
    - Row-based logging is used and it we are creating a temporary table, or
 
1909
    - The binary log is not open.
 
1910
    Otherwise, the statement shall be binlogged.
 
1911
   */
 
1912
  if (!internal_tmp_table &&
 
1913
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1914
    write_bin_log(session, true, session->query, session->query_length);
 
1915
  error= false;
 
1916
unlock_and_end:
 
1917
  pthread_mutex_unlock(&LOCK_open);
 
1918
 
 
1919
err:
1447
1920
  session->set_proc_info("After create");
1448
 
 
 
1921
  delete file;
1449
1922
  return(error);
1450
1923
}
1451
1924
 
1452
 
/**
1453
 
  @note the following two methods implement create [temporary] table.
 
1925
 
 
1926
/*
 
1927
  Database locking aware wrapper for mysql_create_table_no_lock(),
1454
1928
*/
1455
 
static bool drizzle_create_table(Session *session,
1456
 
                                 const TableIdentifier &identifier,
1457
 
                                 HA_CREATE_INFO *create_info,
1458
 
                                 message::Table &table_proto,
1459
 
                                 AlterInfo *alter_info,
1460
 
                                 bool internal_tmp_table,
1461
 
                                 uint32_t select_field_count,
1462
 
                                 bool is_if_not_exists)
 
1929
 
 
1930
bool mysql_create_table(Session *session, const char *db, const char *table_name,
 
1931
                        HA_CREATE_INFO *create_info,
 
1932
                        drizzled::message::Table *table_proto,
 
1933
                        Alter_info *alter_info,
 
1934
                        bool internal_tmp_table,
 
1935
                        uint32_t select_field_count)
1463
1936
{
1464
1937
  Table *name_lock= NULL;
1465
1938
  bool result;
1466
1939
 
1467
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1468
 
  {
1469
 
    result= true;
1470
 
  }
1471
 
  else if (name_lock == NULL)
1472
 
  {
1473
 
    if (is_if_not_exists)
1474
 
    {
1475
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1476
 
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1477
 
                          identifier.getTableName().c_str());
1478
 
      create_info->table_existed= 1;
1479
 
      result= false;
1480
 
    }
1481
 
    else
1482
 
    {
1483
 
      std::string path;
1484
 
      identifier.getSQLPath(path);
1485
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
1940
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1941
  {
 
1942
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
1943
    {
1486
1944
      result= true;
1487
 
    }
1488
 
  }
1489
 
  else
1490
 
  {
1491
 
    result= mysql_create_table_no_lock(session,
1492
 
                                       identifier,
1493
 
                                       create_info,
1494
 
                                       table_proto,
1495
 
                                       alter_info,
1496
 
                                       internal_tmp_table,
1497
 
                                       select_field_count,
1498
 
                                       is_if_not_exists);
1499
 
  }
1500
 
 
 
1945
      goto unlock;
 
1946
    }
 
1947
    if (name_lock == NULL)
 
1948
    {
 
1949
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1950
      {
 
1951
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1952
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1953
                            table_name);
 
1954
        create_info->table_existed= 1;
 
1955
        result= false;
 
1956
      }
 
1957
      else
 
1958
      {
 
1959
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1960
        result= true;
 
1961
      }
 
1962
      goto unlock;
 
1963
    }
 
1964
  }
 
1965
 
 
1966
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1967
                                     table_proto,
 
1968
                                     alter_info,
 
1969
                                     internal_tmp_table,
 
1970
                                     select_field_count);
 
1971
 
 
1972
unlock:
1501
1973
  if (name_lock)
1502
1974
  {
1503
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1975
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1504
1976
    session->unlink_open_table(name_lock);
 
1977
    pthread_mutex_unlock(&LOCK_open);
1505
1978
  }
1506
1979
 
1507
1980
  return(result);
1509
1982
 
1510
1983
 
1511
1984
/*
1512
 
  Database locking aware wrapper for mysql_create_table_no_lock(),
1513
 
*/
1514
 
bool mysql_create_table(Session *session,
1515
 
                        const TableIdentifier &identifier,
1516
 
                        HA_CREATE_INFO *create_info,
1517
 
                        message::Table &table_proto,
1518
 
                        AlterInfo *alter_info,
1519
 
                        bool internal_tmp_table,
1520
 
                        uint32_t select_field_count,
1521
 
                        bool is_if_not_exists)
1522
 
{
1523
 
  if (identifier.isTmp())
1524
 
  {
1525
 
    return mysql_create_table_no_lock(session,
1526
 
                                      identifier,
1527
 
                                      create_info,
1528
 
                                      table_proto,
1529
 
                                      alter_info,
1530
 
                                      internal_tmp_table,
1531
 
                                      select_field_count,
1532
 
                                      is_if_not_exists);
1533
 
  }
1534
 
 
1535
 
  return drizzle_create_table(session,
1536
 
                              identifier,
1537
 
                              create_info,
1538
 
                              table_proto,
1539
 
                              alter_info,
1540
 
                              internal_tmp_table,
1541
 
                              select_field_count,
1542
 
                              is_if_not_exists);
1543
 
}
1544
 
 
1545
 
 
1546
 
/*
1547
1985
** Give the key name after the first field with an optional '_#' after
1548
1986
**/
1549
1987
 
1550
1988
static bool
1551
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1989
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1552
1990
{
1553
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1991
  for (KEY *key=start ; key != end ; key++)
1554
1992
    if (!my_strcasecmp(system_charset_info,name,key->name))
1555
1993
      return 1;
1556
1994
  return 0;
1558
1996
 
1559
1997
 
1560
1998
static char *
1561
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1999
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1562
2000
{
1563
2001
  char buff[MAX_FIELD_NAME],*buff_end;
1564
2002
 
1576
2014
  for (uint32_t i=2 ; i< 100; i++)
1577
2015
  {
1578
2016
    *buff_end= '_';
1579
 
    internal::int10_to_str(i, buff_end+1, 10);
 
2017
    int10_to_str(i, buff_end+1, 10);
1580
2018
    if (!check_if_keyname_exists(buff,start,end))
1581
 
      return memory::sql_strdup(buff);
 
2019
      return sql_strdup(buff);
1582
2020
  }
1583
2021
  return (char*) "not_specified";               // Should never happen
1584
2022
}
1588
2026
** Alter a table definition
1589
2027
****************************************************************************/
1590
2028
 
 
2029
 
1591
2030
/*
1592
2031
  Rename a table.
1593
2032
 
1594
2033
  SYNOPSIS
1595
2034
    mysql_rename_table()
1596
 
      session
1597
 
      base                      The plugin::StorageEngine handle.
 
2035
      base                      The StorageEngine handle.
1598
2036
      old_db                    The old database name.
1599
2037
      old_name                  The old table name.
1600
2038
      new_db                    The new database name.
1601
2039
      new_name                  The new table name.
 
2040
      flags                     flags for build_table_filename().
 
2041
                                FN_FROM_IS_TMP old_name is temporary.
 
2042
                                FN_TO_IS_TMP   new_name is temporary.
 
2043
                                NO_FRM_RENAME  Don't rename the FRM file
 
2044
                                but only the table in the storage engine.
1602
2045
 
1603
2046
  RETURN
1604
2047
    false   OK
1606
2049
*/
1607
2050
 
1608
2051
bool
1609
 
mysql_rename_table(Session &session,
1610
 
                   plugin::StorageEngine *base,
1611
 
                   const TableIdentifier &from,
1612
 
                   const TableIdentifier &to)
 
2052
mysql_rename_table(StorageEngine *base, const char *old_db,
 
2053
                   const char *old_name, const char *new_db,
 
2054
                   const char *new_name, uint32_t flags)
1613
2055
{
 
2056
  Session *session= current_session;
 
2057
  char from[FN_REFLEN], to[FN_REFLEN];
 
2058
  char *from_base= from, *to_base= to;
1614
2059
  int error= 0;
1615
2060
 
1616
2061
  assert(base);
1617
2062
 
1618
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
2063
  build_table_filename(from, sizeof(from), old_db, old_name,
 
2064
                       flags & FN_FROM_IS_TMP);
 
2065
  build_table_filename(to, sizeof(to), new_db, new_name,
 
2066
                       flags & FN_TO_IS_TMP);
 
2067
 
 
2068
  if (!(error=base->renameTable(session, from_base, to_base)))
1619
2069
  {
1620
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1621
 
    return true;
 
2070
    if(!(flags & NO_FRM_RENAME)
 
2071
       && rename_table_proto_file(from_base, to_base))
 
2072
    {
 
2073
      error= my_errno;
 
2074
      base->renameTable(session, to_base, from_base);
 
2075
    }
1622
2076
  }
1623
2077
 
1624
 
  error= base->renameTable(session, from, to);
1625
 
 
1626
2078
  if (error == HA_ERR_WRONG_COMMAND)
1627
 
  {
1628
2079
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1629
 
  }
1630
2080
  else if (error)
1631
 
  {
1632
 
    std::string from_path;
1633
 
    std::string to_path;
1634
 
 
1635
 
    from.getSQLPath(from_path);
1636
 
    to.getSQLPath(to_path);
1637
 
 
1638
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1639
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1640
 
 
1641
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1642
 
  }
1643
 
 
1644
 
  return error ? true : false; 
 
2081
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
2082
  return(error != 0);
1645
2083
}
1646
2084
 
1647
2085
 
1650
2088
 
1651
2089
  SYNOPSIS
1652
2090
    wait_while_table_is_used()
1653
 
    session                     Thread Cursor
 
2091
    session                     Thread handler
1654
2092
    table               Table to remove from cache
1655
2093
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1656
2094
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1660
2098
   the table is closed.
1661
2099
 
1662
2100
  PREREQUISITES
1663
 
    Lock on table::Cache::singleton().mutex()
 
2101
    Lock on LOCK_open
1664
2102
    Win32 clients must also have a WRITE LOCK on the table !
1665
2103
*/
1666
2104
 
1668
2106
                              enum ha_extra_function function)
1669
2107
{
1670
2108
 
1671
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
2109
  safe_mutex_assert_owner(&LOCK_open);
1672
2110
 
1673
 
  table->cursor->extra(function);
 
2111
  table->file->extra(function);
1674
2112
  /* Mark all tables that are in use as 'old' */
1675
 
  session->abortLock(table);    /* end threads waiting on lock */
 
2113
  mysql_lock_abort(session, table, true);       /* end threads waiting on lock */
1676
2114
 
1677
2115
  /* Wait until all there are no other threads that has this table open */
1678
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1679
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
2116
  remove_table_from_cache(session, table->s->db.str,
 
2117
                          table->s->table_name.str,
 
2118
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1680
2119
}
1681
2120
 
1682
2121
/*
1684
2123
 
1685
2124
  SYNOPSIS
1686
2125
    close_cached_table()
1687
 
    session                     Thread Cursor
 
2126
    session                     Thread handler
1688
2127
    table               Table to remove from cache
1689
2128
 
1690
2129
  NOTES
1692
2131
    reopen the table.
1693
2132
 
1694
2133
  PREREQUISITES
1695
 
    Lock on table::Cache::singleton().mutex()
 
2134
    Lock on LOCK_open
1696
2135
    Win32 clients must also have a WRITE LOCK on the table !
1697
2136
*/
1698
2137
 
1703
2142
  /* Close lock if this is not got with LOCK TABLES */
1704
2143
  if (lock)
1705
2144
  {
1706
 
    unlockTables(lock);
 
2145
    mysql_unlock_tables(this, lock);
1707
2146
    lock= NULL;                 // Start locked threads
1708
2147
  }
1709
2148
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1710
2149
  unlink_open_table(table);
1711
2150
 
1712
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1713
 
  locking::broadcast_refresh();
 
2151
  /* When lock on LOCK_open is freed other threads can continue */
 
2152
  broadcast_refresh();
1714
2153
}
1715
2154
 
1716
2155
/*
1724
2163
                              const char *operator_name,
1725
2164
                              thr_lock_type lock_type,
1726
2165
                              bool open_for_modify,
1727
 
                              int (Cursor::*operator_func)(Session *,
 
2166
                              bool no_warnings_for_error,
 
2167
                              uint32_t extra_open_options,
 
2168
                              int (*prepare_func)(Session *, TableList *,
 
2169
                                                  HA_CHECK_OPT *),
 
2170
                              int (handler::*operator_func)(Session *,
1728
2171
                                                            HA_CHECK_OPT *))
1729
2172
{
1730
2173
  TableList *table;
1731
2174
  Select_Lex *select= &session->lex->select_lex;
1732
2175
  List<Item> field_list;
1733
2176
  Item *item;
 
2177
  Protocol *protocol= session->protocol;
1734
2178
  LEX *lex= session->lex;
1735
2179
  int result_code= 0;
1736
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1737
2180
  const CHARSET_INFO * const cs= system_charset_info;
1738
2181
 
1739
2182
  if (! session->endActiveTransaction())
1748
2191
  item->maybe_null = 1;
1749
2192
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1750
2193
  item->maybe_null = 1;
1751
 
  if (session->client->sendFields(&field_list))
1752
 
    return true;
 
2194
  if (protocol->sendFields(&field_list,
 
2195
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
2196
    return(true);
1753
2197
 
1754
2198
  for (table= tables; table; table= table->next_local)
1755
2199
  {
1756
2200
    char table_name[NAME_LEN*2+2];
 
2201
    char* db = table->db;
1757
2202
    bool fatal_error=0;
1758
2203
 
1759
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
2204
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2205
    session->open_options|= extra_open_options;
1760
2206
    table->lock_type= lock_type;
1761
2207
    /* open only one table from local list of command */
1762
2208
    {
1769
2215
      /*
1770
2216
        Time zone tables and SP tables can be add to lex->query_tables list,
1771
2217
        so it have to be prepared.
1772
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2218
        TODO: Investigate if we can put extra tables into argument instead of
 
2219
        using lex->query_tables
1773
2220
      */
1774
2221
      lex->query_tables= table;
1775
2222
      lex->query_tables_last= &table->next_global;
1776
2223
      lex->query_tables_own_last= 0;
1777
 
      session->no_warnings_for_error= 0;
 
2224
      session->no_warnings_for_error= no_warnings_for_error;
1778
2225
 
1779
 
      session->openTablesLock(table);
 
2226
      session->open_and_lock_tables(table);
1780
2227
      session->no_warnings_for_error= 0;
1781
2228
      table->next_global= save_next_global;
1782
2229
      table->next_local= save_next_local;
 
2230
      session->open_options&= ~extra_open_options;
 
2231
    }
 
2232
 
 
2233
    if (prepare_func)
 
2234
    {
 
2235
      switch ((*prepare_func)(session, table, check_opt)) {
 
2236
      case  1:           // error, message written to net
 
2237
        ha_autocommit_or_rollback(session, 1);
 
2238
        session->endTransaction(ROLLBACK);
 
2239
        session->close_thread_tables();
 
2240
        continue;
 
2241
      case -1:           // error, message could be written to net
 
2242
        /* purecov: begin inspected */
 
2243
        goto err;
 
2244
        /* purecov: end */
 
2245
      default:           // should be 0 otherwise
 
2246
        ;
 
2247
      }
1783
2248
    }
1784
2249
 
1785
2250
    /*
1801
2266
 
1802
2267
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
1803
2268
    {
 
2269
      /* purecov: begin inspected */
1804
2270
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1805
2271
      uint32_t length;
1806
 
      session->client->store(table_name);
1807
 
      session->client->store(operator_name);
1808
 
      session->client->store(STRING_WITH_LEN("error"));
 
2272
      protocol->prepareForResend();
 
2273
      protocol->store(table_name);
 
2274
      protocol->store(operator_name);
 
2275
      protocol->store(STRING_WITH_LEN("error"));
1809
2276
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1810
2277
                       table_name);
1811
 
      session->client->store(buff, length);
1812
 
      transaction_services.autocommitOrRollback(session, false);
 
2278
      protocol->store(buff, length);
 
2279
      ha_autocommit_or_rollback(session, 0);
1813
2280
      session->endTransaction(COMMIT);
1814
2281
      session->close_thread_tables();
1815
2282
      lex->reset_query_tables_list(false);
1816
2283
      table->table=0;                           // For query cache
1817
 
      if (session->client->flush())
 
2284
      if (protocol->write())
1818
2285
        goto err;
1819
2286
      continue;
 
2287
      /* purecov: end */
1820
2288
    }
1821
2289
 
1822
2290
    /* Close all instances of the table to allow repair to rename files */
1823
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2291
    if (lock_type == TL_WRITE && table->table->s->version)
1824
2292
    {
1825
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1826
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1827
 
                                                  "Waiting to get writelock");
1828
 
      session->abortLock(table->table);
1829
 
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1830
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
2293
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2294
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
2295
                                              "Waiting to get writelock");
 
2296
      mysql_lock_abort(session,table->table, true);
 
2297
      remove_table_from_cache(session, table->table->s->db.str,
 
2298
                              table->table->s->table_name.str,
 
2299
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2300
                              RTFC_CHECK_KILLED_FLAG);
1831
2301
      session->exit_cond(old_message);
1832
 
      if (session->getKilled())
 
2302
      if (session->killed)
1833
2303
        goto err;
1834
2304
      open_for_modify= 0;
1835
2305
    }
1836
2306
 
1837
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
2307
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2308
    {
 
2309
      /* purecov: begin inspected */
 
2310
      protocol->prepareForResend();
 
2311
      protocol->store(table_name);
 
2312
      protocol->store(operator_name);
 
2313
      protocol->store(STRING_WITH_LEN("warning"));
 
2314
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2315
      if (protocol->write())
 
2316
        goto err;
 
2317
      /* purecov: end */
 
2318
    }
 
2319
 
 
2320
    result_code = (table->table->file->*operator_func)(session, check_opt);
1838
2321
 
1839
2322
send_result:
1840
2323
 
1845
2328
      DRIZZLE_ERROR *err;
1846
2329
      while ((err= it++))
1847
2330
      {
1848
 
        session->client->store(table_name);
1849
 
        session->client->store(operator_name);
1850
 
        session->client->store(warning_level_names[err->level].str,
1851
 
                               warning_level_names[err->level].length);
1852
 
        session->client->store(err->msg);
1853
 
        if (session->client->flush())
 
2331
        protocol->prepareForResend();
 
2332
        protocol->store(table_name);
 
2333
        protocol->store(operator_name);
 
2334
        protocol->store(warning_level_names[err->level].str,
 
2335
                        warning_level_names[err->level].length);
 
2336
        protocol->store(err->msg);
 
2337
        if (protocol->write())
1854
2338
          goto err;
1855
2339
      }
1856
2340
      drizzle_reset_errors(session, true);
1857
2341
    }
1858
 
    session->client->store(table_name);
1859
 
    session->client->store(operator_name);
 
2342
    protocol->prepareForResend();
 
2343
    protocol->store(table_name);
 
2344
    protocol->store(operator_name);
 
2345
 
 
2346
send_result_message:
1860
2347
 
1861
2348
    switch (result_code) {
1862
2349
    case HA_ADMIN_NOT_IMPLEMENTED:
1864
2351
        char buf[ERRMSGSIZE+20];
1865
2352
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1866
2353
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1867
 
        session->client->store(STRING_WITH_LEN("note"));
1868
 
        session->client->store(buf, length);
 
2354
        protocol->store(STRING_WITH_LEN("note"));
 
2355
        protocol->store(buf, length);
1869
2356
      }
1870
2357
      break;
1871
2358
 
1872
2359
    case HA_ADMIN_OK:
1873
 
      session->client->store(STRING_WITH_LEN("status"));
1874
 
      session->client->store(STRING_WITH_LEN("OK"));
 
2360
      protocol->store(STRING_WITH_LEN("status"));
 
2361
      protocol->store(STRING_WITH_LEN("OK"));
1875
2362
      break;
1876
2363
 
1877
2364
    case HA_ADMIN_FAILED:
1878
 
      session->client->store(STRING_WITH_LEN("status"));
1879
 
      session->client->store(STRING_WITH_LEN("Operation failed"));
 
2365
      protocol->store(STRING_WITH_LEN("status"));
 
2366
      protocol->store(STRING_WITH_LEN("Operation failed"));
1880
2367
      break;
1881
2368
 
1882
2369
    case HA_ADMIN_REJECT:
1883
 
      session->client->store(STRING_WITH_LEN("status"));
1884
 
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
 
2370
      protocol->store(STRING_WITH_LEN("status"));
 
2371
      protocol->store(STRING_WITH_LEN("Operation need committed state"));
1885
2372
      open_for_modify= false;
1886
2373
      break;
1887
2374
 
1888
2375
    case HA_ADMIN_ALREADY_DONE:
1889
 
      session->client->store(STRING_WITH_LEN("status"));
1890
 
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
 
2376
      protocol->store(STRING_WITH_LEN("status"));
 
2377
      protocol->store(STRING_WITH_LEN("Table is already up to date"));
1891
2378
      break;
1892
2379
 
1893
2380
    case HA_ADMIN_CORRUPT:
1894
 
      session->client->store(STRING_WITH_LEN("error"));
1895
 
      session->client->store(STRING_WITH_LEN("Corrupt"));
 
2381
      protocol->store(STRING_WITH_LEN("error"));
 
2382
      protocol->store(STRING_WITH_LEN("Corrupt"));
1896
2383
      fatal_error=1;
1897
2384
      break;
1898
2385
 
1899
2386
    case HA_ADMIN_INVALID:
1900
 
      session->client->store(STRING_WITH_LEN("error"));
1901
 
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1902
 
      break;
 
2387
      protocol->store(STRING_WITH_LEN("error"));
 
2388
      protocol->store(STRING_WITH_LEN("Invalid argument"));
 
2389
      break;
 
2390
 
 
2391
    case HA_ADMIN_TRY_ALTER:
 
2392
    {
 
2393
      /*
 
2394
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2395
        "try with alter", so here we close the table, do an ALTER Table,
 
2396
        reopen the table and do ha_innobase::analyze() on it.
 
2397
      */
 
2398
      ha_autocommit_or_rollback(session, 0);
 
2399
      session->close_thread_tables();
 
2400
      TableList *save_next_local= table->next_local,
 
2401
                 *save_next_global= table->next_global;
 
2402
      table->next_local= table->next_global= 0;
 
2403
      result_code= mysql_recreate_table(session, table);
 
2404
      /*
 
2405
        mysql_recreate_table() can push OK or ERROR.
 
2406
        Clear 'OK' status. If there is an error, keep it:
 
2407
        we will store the error message in a result set row
 
2408
        and then clear.
 
2409
      */
 
2410
      if (session->main_da.is_ok())
 
2411
        session->main_da.reset_diagnostics_area();
 
2412
      ha_autocommit_or_rollback(session, 0);
 
2413
      session->close_thread_tables();
 
2414
      if (!result_code) // recreation went ok
 
2415
      {
 
2416
        if ((table->table= session->open_ltable(table, lock_type)) &&
 
2417
            ((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
 
2418
          result_code= 0; // analyze went ok
 
2419
      }
 
2420
      if (result_code) // either mysql_recreate_table or analyze failed
 
2421
      {
 
2422
        assert(session->is_error());
 
2423
        if (session->is_error())
 
2424
        {
 
2425
          const char *err_msg= session->main_da.message();
 
2426
          if (!session->protocol->isConnected())
 
2427
          {
 
2428
            errmsg_printf(ERRMSG_LVL_ERROR, "%s", err_msg);
 
2429
          }
 
2430
          else
 
2431
          {
 
2432
            /* Hijack the row already in-progress. */
 
2433
            protocol->store(STRING_WITH_LEN("error"));
 
2434
            protocol->store(err_msg);
 
2435
            (void)protocol->write();
 
2436
            /* Start off another row for HA_ADMIN_FAILED */
 
2437
            protocol->prepareForResend();
 
2438
            protocol->store(table_name);
 
2439
            protocol->store(operator_name);
 
2440
          }
 
2441
          session->clear_error();
 
2442
        }
 
2443
      }
 
2444
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2445
      table->next_local= save_next_local;
 
2446
      table->next_global= save_next_global;
 
2447
      goto send_result_message;
 
2448
    }
 
2449
    case HA_ADMIN_NEEDS_UPGRADE:
 
2450
    case HA_ADMIN_NEEDS_ALTER:
 
2451
    {
 
2452
      char buf[ERRMSGSIZE];
 
2453
      uint32_t length;
 
2454
 
 
2455
      protocol->store(STRING_WITH_LEN("error"));
 
2456
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2457
      protocol->store(buf, length);
 
2458
      fatal_error=1;
 
2459
      break;
 
2460
    }
1903
2461
 
1904
2462
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1905
2463
      {
1907
2465
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
2466
                             _("Unknown - internal error %d during operation"),
1909
2467
                             result_code);
1910
 
        session->client->store(STRING_WITH_LEN("error"));
1911
 
        session->client->store(buf, length);
 
2468
        protocol->store(STRING_WITH_LEN("error"));
 
2469
        protocol->store(buf, length);
1912
2470
        fatal_error=1;
1913
2471
        break;
1914
2472
      }
1916
2474
    if (table->table)
1917
2475
    {
1918
2476
      if (fatal_error)
1919
 
      {
1920
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1921
 
      }
 
2477
        table->table->s->version=0;               // Force close of table
1922
2478
      else if (open_for_modify)
1923
2479
      {
1924
 
        if (table->table->getShare()->getType())
1925
 
        {
1926
 
          table->table->cursor->info(HA_STATUS_CONST);
1927
 
        }
 
2480
        if (table->table->s->tmp_table)
 
2481
          table->table->file->info(HA_STATUS_CONST);
1928
2482
        else
1929
2483
        {
1930
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1931
 
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1932
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
2484
          pthread_mutex_lock(&LOCK_open);
 
2485
          remove_table_from_cache(session, table->table->s->db.str,
 
2486
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2487
          pthread_mutex_unlock(&LOCK_open);
1933
2488
        }
1934
2489
      }
1935
2490
    }
1936
 
    transaction_services.autocommitOrRollback(session, false);
 
2491
    ha_autocommit_or_rollback(session, 0);
1937
2492
    session->endTransaction(COMMIT);
1938
2493
    session->close_thread_tables();
1939
2494
    table->table=0;                             // For query cache
1940
 
    if (session->client->flush())
 
2495
    if (protocol->write())
1941
2496
      goto err;
1942
2497
  }
1943
2498
 
1945
2500
  return(false);
1946
2501
 
1947
2502
err:
1948
 
  transaction_services.autocommitOrRollback(session, true);
 
2503
  ha_autocommit_or_rollback(session, 1);
1949
2504
  session->endTransaction(ROLLBACK);
1950
2505
  session->close_thread_tables();                       // Shouldn't be needed
1951
2506
  if (table)
1953
2508
  return(true);
1954
2509
}
1955
2510
 
1956
 
  /*
1957
 
    Create a new table by copying from source table
1958
 
 
1959
 
    Altough exclusive name-lock on target table protects us from concurrent
1960
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
1961
 
    to plugin::StorageEngine::createTable() in critical section protected by
1962
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1963
 
    disregard name-locks, like I_S implementation, for example. This is a
1964
 
    temporary and should not be copied. Instead we should fix our code to
1965
 
    always honor name-locks.
1966
 
 
1967
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1968
 
    during the call to plugin::StorageEngine::createTable().
1969
 
    See bug #28614 for more info.
1970
 
  */
1971
 
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
 
                                 const TableIdentifier &destination_identifier,
1973
 
                                 const TableIdentifier &src_table,
1974
 
                                 bool is_engine_set)
1975
 
{
1976
 
  int protoerr= EEXIST;
1977
 
  message::Table new_proto;
1978
 
  message::table::shared_ptr src_proto;
1979
 
 
1980
 
  protoerr= plugin::StorageEngine::getTableDefinition(session,
1981
 
                                                      src_table,
1982
 
                                                      src_proto);
1983
 
  new_proto.CopyFrom(*src_proto);
1984
 
 
1985
 
  if (destination_identifier.isTmp())
 
2511
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2512
{
 
2513
  return(mysql_admin_table(session, tables, check_opt,
 
2514
                           "optimize", TL_WRITE, 1,0,0,0,
 
2515
                           &handler::ha_optimize));
 
2516
}
 
2517
 
 
2518
 
 
2519
/*
 
2520
  Assigned specified indexes for a table into key cache
 
2521
 
 
2522
  SYNOPSIS
 
2523
    mysql_assign_to_keycache()
 
2524
    session             Thread object
 
2525
    tables      Table list (one table only)
 
2526
 
 
2527
  RETURN VALUES
 
2528
   false ok
 
2529
   true  error
 
2530
*/
 
2531
 
 
2532
bool mysql_assign_to_keycache(Session* session, TableList* tables,
 
2533
                             LEX_STRING *key_cache_name)
 
2534
{
 
2535
  HA_CHECK_OPT check_opt;
 
2536
  KEY_CACHE *key_cache;
 
2537
 
 
2538
  check_opt.init();
 
2539
  pthread_mutex_lock(&LOCK_global_system_variables);
 
2540
  if (!(key_cache= get_key_cache(key_cache_name)))
1986
2541
  {
1987
 
    new_proto.set_type(message::Table::TEMPORARY);
 
2542
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
2543
    my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
 
2544
    return(true);
1988
2545
  }
 
2546
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
2547
  check_opt.key_cache= key_cache;
 
2548
  return(mysql_admin_table(session, tables, &check_opt,
 
2549
                                "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
 
2550
                                0, 0, &handler::assign_to_keycache));
 
2551
}
 
2552
 
 
2553
 
 
2554
/*
 
2555
  Reassign all tables assigned to a key cache to another key cache
 
2556
 
 
2557
  SYNOPSIS
 
2558
    reassign_keycache_tables()
 
2559
    session             Thread object
 
2560
    src_cache   Reference to the key cache to clean up
 
2561
    dest_cache  New key cache
 
2562
 
 
2563
  NOTES
 
2564
    This is called when one sets a key cache size to zero, in which
 
2565
    case we have to move the tables associated to this key cache to
 
2566
    the "default" one.
 
2567
 
 
2568
    One has to ensure that one never calls this function while
 
2569
    some other thread is changing the key cache. This is assured by
 
2570
    the caller setting src_cache->in_init before calling this function.
 
2571
 
 
2572
    We don't delete the old key cache as there may still be pointers pointing
 
2573
    to it for a while after this function returns.
 
2574
 
 
2575
 RETURN VALUES
 
2576
    0     ok
 
2577
*/
 
2578
 
 
2579
int reassign_keycache_tables(Session *,
 
2580
                             KEY_CACHE *src_cache,
 
2581
                             KEY_CACHE *dst_cache)
 
2582
{
 
2583
  assert(src_cache != dst_cache);
 
2584
  assert(src_cache->in_init);
 
2585
  src_cache->param_buff_size= 0;                // Free key cache
 
2586
  ha_resize_key_cache(src_cache);
 
2587
  ha_change_key_cache(src_cache, dst_cache);
 
2588
  return 0;
 
2589
}
 
2590
 
 
2591
/**
 
2592
  @brief          Create frm file based on I_S table
 
2593
 
 
2594
  @param[in]      session                      thread handler
 
2595
  @param[in]      schema_table             I_S table
 
2596
  @param[in]      dst_path                 path where frm should be created
 
2597
  @param[in]      create_info              Create info
 
2598
 
 
2599
  @return         Operation status
 
2600
    @retval       0                        success
 
2601
    @retval       1                        error
 
2602
*/
 
2603
bool mysql_create_like_schema_frm(Session* session, TableList* schema_table,
 
2604
                                  char *dst_path, HA_CREATE_INFO *create_info)
 
2605
{
 
2606
  HA_CREATE_INFO local_create_info;
 
2607
  Alter_info alter_info;
 
2608
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
2609
  uint32_t keys= schema_table->table->s->keys;
 
2610
  uint32_t db_options= 0;
 
2611
 
 
2612
  memset(&local_create_info, 0, sizeof(local_create_info));
 
2613
  local_create_info.db_type= schema_table->table->s->db_type();
 
2614
  local_create_info.row_type= schema_table->table->s->row_type;
 
2615
  local_create_info.default_table_charset=default_charset_info;
 
2616
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
2617
  schema_table->table->use_all_columns();
 
2618
  if (mysql_prepare_alter_table(session, schema_table->table,
 
2619
                                &local_create_info, &alter_info))
 
2620
    return true;
 
2621
 
 
2622
  if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
 
2623
                                 tmp_table, &db_options,
 
2624
                                 schema_table->table->file,
 
2625
                                 &schema_table->table->s->key_info, &keys, 0))
 
2626
    return true;
 
2627
 
 
2628
  local_create_info.max_rows= 0;
 
2629
  drizzled::message::Table table_proto;
 
2630
  table_proto.set_name("system_stupid_i_s_fix_nonsense");
 
2631
  if(tmp_table)
 
2632
    table_proto.set_type(drizzled::message::Table::TEMPORARY);
1989
2633
  else
1990
 
  {
1991
 
    new_proto.set_type(message::Table::STANDARD);
1992
 
  }
1993
 
 
1994
 
  if (is_engine_set)
1995
 
  {
1996
 
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
1997
 
  }
1998
 
 
1999
 
  { // We now do a selective copy of elements on to the new table.
2000
 
    new_proto.set_name(create_table_proto.name());
2001
 
    new_proto.set_schema(create_table_proto.schema());
2002
 
    new_proto.set_catalog(create_table_proto.catalog());
2003
 
  }
2004
 
 
2005
 
  if (protoerr && protoerr != EEXIST)
2006
 
  {
2007
 
    if (errno == ENOENT)
2008
 
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2009
 
    else
2010
 
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2011
 
 
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  /*
2016
 
    As mysql_truncate don't work on a new table at this stage of
2017
 
    creation, instead create the table directly (for both normal
2018
 
    and temporary tables).
2019
 
  */
2020
 
  int err= plugin::StorageEngine::createTable(session,
2021
 
                                              destination_identifier,
2022
 
                                              new_proto);
2023
 
 
2024
 
  if (err == false && not destination_identifier.isTmp())
2025
 
  {
2026
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2027
 
    transaction_services.createTable(&session, new_proto);
2028
 
  }
2029
 
 
2030
 
  return err ? false : true;
 
2634
    table_proto.set_type(drizzled::message::Table::STANDARD);
 
2635
 
 
2636
  {
 
2637
    drizzled::message::Table::StorageEngine *protoengine;
 
2638
    protoengine= table_proto.mutable_engine();
 
2639
 
 
2640
    StorageEngine *engine= local_create_info.db_type;
 
2641
 
 
2642
    protoengine->set_name(engine->getName());
 
2643
  }
 
2644
 
 
2645
  if (rea_create_table(session, dst_path, "system_tmp", "system_stupid_i_s_fix_nonsense",
 
2646
                       &table_proto,
 
2647
                       &local_create_info, alter_info.create_list,
 
2648
                       keys, schema_table->table->s->key_info,
 
2649
                       true))
 
2650
    return true;
 
2651
 
 
2652
  return false;
2031
2653
}
2032
2654
 
2033
2655
/*
2045
2667
    true  error
2046
2668
*/
2047
2669
 
2048
 
bool mysql_create_like_table(Session* session,
2049
 
                             const TableIdentifier &destination_identifier,
2050
 
                             TableList* table, TableList* src_table,
2051
 
                             message::Table &create_table_proto,
2052
 
                             bool is_if_not_exists,
2053
 
                             bool is_engine_set)
 
2670
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2671
                             HA_CREATE_INFO *create_info)
2054
2672
{
 
2673
  Table *name_lock= 0;
 
2674
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2675
  uint32_t dst_path_length;
 
2676
  char *db= table->db;
 
2677
  char *table_name= table->table_name;
 
2678
  int  err;
2055
2679
  bool res= true;
2056
2680
  uint32_t not_used;
2057
2681
 
2058
2682
  /*
2059
2683
    By opening source table we guarantee that it exists and no concurrent
2060
2684
    DDL operation will mess with it. Later we also take an exclusive
2061
 
    name-lock on target table name, which makes copying of .frm cursor,
2062
 
    call to plugin::StorageEngine::createTable() and binlogging atomic
2063
 
    against concurrent DML and DDL operations on target table.
2064
 
    Thus by holding both these "locks" we ensure that our statement is
2065
 
    properly isolated from all concurrent operations which matter.
 
2685
    name-lock on target table name, which makes copying of .frm file,
 
2686
    call to ha_create_table() and binlogging atomic against concurrent DML
 
2687
    and DDL operations on target table. Thus by holding both these "locks"
 
2688
    we ensure that our statement is properly isolated from all concurrent
 
2689
    operations which matter.
2066
2690
  */
2067
 
  if (session->open_tables_from_list(&src_table, &not_used))
 
2691
  if (session->open_tables_from_list(&src_table, &not_used, 0))
2068
2692
    return true;
2069
2693
 
2070
 
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2071
 
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2072
 
 
2073
 
 
 
2694
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2074
2695
 
2075
2696
  /*
2076
2697
    Check that destination tables does not exist. Note that its name
2077
2698
    was already checked when it was added to the table list.
2078
 
 
2079
 
    For temporary tables we don't aim to grab locks.
2080
 
  */
2081
 
  bool table_exists= false;
2082
 
  if (destination_identifier.isTmp())
2083
 
  {
2084
 
    if (session->find_temporary_table(destination_identifier))
2085
 
    {
2086
 
      table_exists= true;
2087
 
    }
2088
 
    else
2089
 
    {
2090
 
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
 
                                             src_identifier, is_engine_set);
2092
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2093
 
      {
2094
 
        (void) session->rm_temporary_table(destination_identifier, true);
2095
 
      }
2096
 
      else if (not session->open_temporary_table(destination_identifier))
2097
 
      {
2098
 
        // We created, but we can't open... also, a hack.
2099
 
        (void) session->rm_temporary_table(destination_identifier, true);
2100
 
      }
2101
 
      else
2102
 
      {
2103
 
        res= false;
2104
 
      }
2105
 
    }
2106
 
  }
2107
 
  else // Standard table which will require locks.
2108
 
  {
2109
 
    Table *name_lock= 0;
2110
 
 
2111
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2112
 
    {
2113
 
      if (name_lock)
2114
 
      {
2115
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2116
 
        session->unlink_open_table(name_lock);
2117
 
      }
2118
 
 
2119
 
      return res;
2120
 
    }
2121
 
 
2122
 
    if (not name_lock)
2123
 
    {
2124
 
      table_exists= true;
2125
 
    }
2126
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2127
 
    {
2128
 
      table_exists= true;
2129
 
    }
2130
 
    else // Otherwise we create the table
2131
 
    {
2132
 
      bool was_created;
2133
 
      {
2134
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2135
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2136
 
                                               src_identifier, is_engine_set);
2137
 
      }
2138
 
 
2139
 
      // So we blew the creation of the table, and we scramble to clean up
2140
 
      // anything that might have been created (read... it is a hack)
2141
 
      if (not was_created)
2142
 
      {
2143
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2144
 
      } 
2145
 
      else
2146
 
      {
2147
 
        res= false;
2148
 
      }
2149
 
    }
2150
 
 
 
2699
  */
 
2700
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2701
  {
 
2702
    if (session->find_temporary_table(db, table_name))
 
2703
      goto table_exists;
 
2704
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
 
2705
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
 
2706
  }
 
2707
  else
 
2708
  {
 
2709
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
2710
      goto err;
 
2711
    if (!name_lock)
 
2712
      goto table_exists;
 
2713
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2714
                                          db, table_name, false);
 
2715
    if (table_proto_exists(dst_path)==EEXIST)
 
2716
      goto table_exists;
 
2717
  }
 
2718
 
 
2719
  /*
 
2720
    Create a new table by copying from source table
 
2721
 
 
2722
    Altough exclusive name-lock on target table protects us from concurrent
 
2723
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2724
    to ha_create_table() in critical section protected by LOCK_open in order
 
2725
    to provide minimal atomicity against operations which disregard name-locks,
 
2726
    like I_S implementation, for example. This is a temporary and should not
 
2727
    be copied. Instead we should fix our code to always honor name-locks.
 
2728
 
 
2729
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2730
    during the call to ha_create_table(). See bug #28614 for more info.
 
2731
  */
 
2732
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2733
  if (src_table->schema_table)
 
2734
  {
 
2735
    if (mysql_create_like_schema_frm(session, src_table, dst_path, create_info))
 
2736
    {
 
2737
      pthread_mutex_unlock(&LOCK_open);
 
2738
      goto err;
 
2739
    }
 
2740
  }
 
2741
  else
 
2742
  {
 
2743
    int dfecopyr= copy_table_proto_file(src_path, dst_path);
 
2744
 
 
2745
    if(dfecopyr)
 
2746
    {
 
2747
      if (my_errno == ENOENT)
 
2748
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2749
      else
 
2750
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2751
      pthread_mutex_unlock(&LOCK_open);
 
2752
      goto err;
 
2753
    }
 
2754
  }
 
2755
 
 
2756
  /*
 
2757
    As mysql_truncate don't work on a new table at this stage of
 
2758
    creation, instead create the table directly (for both normal
 
2759
    and temporary tables).
 
2760
  */
 
2761
 
 
2762
  err= ha_create_table(session, dst_path, db, table_name, create_info, 1);
 
2763
  pthread_mutex_unlock(&LOCK_open);
 
2764
 
 
2765
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2766
  {
 
2767
    if (err || !open_temporary_table(session, dst_path, db, table_name, 1,
 
2768
                                     OTM_OPEN))
 
2769
    {
 
2770
      (void) rm_temporary_table(create_info->db_type,
 
2771
                                dst_path);
 
2772
      goto err;     /* purecov: inspected */
 
2773
    }
 
2774
  }
 
2775
  else if (err)
 
2776
  {
 
2777
    (void) quick_rm_table(create_info->db_type, db,
 
2778
                          table_name, false); /* purecov: inspected */
 
2779
    goto err;       /* purecov: inspected */
 
2780
  }
 
2781
 
 
2782
  /*
 
2783
    We have to write the query before we unlock the tables.
 
2784
  */
 
2785
  {
 
2786
    /*
 
2787
       Since temporary tables are not replicated under row-based
 
2788
       replication, CREATE TABLE ... LIKE ... needs special
 
2789
       treatement.  We have four cases to consider, according to the
 
2790
       following decision table:
 
2791
 
 
2792
           ==== ========= ========= ==============================
 
2793
           Case    Target    Source Write to binary log
 
2794
           ==== ========= ========= ==============================
 
2795
           1       normal    normal Original statement
 
2796
           2       normal temporary Generated statement
 
2797
           3    temporary    normal Nothing
 
2798
           4    temporary temporary Nothing
 
2799
           ==== ========= ========= ==============================
 
2800
    */
 
2801
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2802
    {
 
2803
      if (src_table->table->s->tmp_table)               // Case 2
 
2804
      {
 
2805
        char buf[2048];
 
2806
        String query(buf, sizeof(buf), system_charset_info);
 
2807
        query.length(0);  // Have to zero it since constructor doesn't
 
2808
 
 
2809
 
 
2810
        /*
 
2811
          Here we open the destination table, on which we already have
 
2812
          name-lock. This is needed for store_create_info() to work.
 
2813
          The table will be closed by unlink_open_table() at the end
 
2814
          of this function.
 
2815
        */
 
2816
        table->table= name_lock;
 
2817
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2818
        if (session->reopen_name_locked_table(table, false))
 
2819
        {
 
2820
          pthread_mutex_unlock(&LOCK_open);
 
2821
          goto err;
 
2822
        }
 
2823
        pthread_mutex_unlock(&LOCK_open);
 
2824
 
 
2825
        int result= store_create_info(table, &query, create_info);
 
2826
 
 
2827
        assert(result == 0); // store_create_info() always return 0
 
2828
        write_bin_log(session, true, query.ptr(), query.length());
 
2829
      }
 
2830
      else                                      // Case 1
 
2831
        write_bin_log(session, true, session->query, session->query_length);
 
2832
    }
 
2833
  }
 
2834
 
 
2835
  res= false;
 
2836
  goto err;
 
2837
 
 
2838
table_exists:
 
2839
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2840
  {
 
2841
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2842
    snprintf(warn_buff, sizeof(warn_buff),
 
2843
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2844
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2845
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2846
    res= false;
 
2847
  }
 
2848
  else
 
2849
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2850
 
 
2851
err:
 
2852
  if (name_lock)
 
2853
  {
 
2854
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2855
    session->unlink_open_table(name_lock);
 
2856
    pthread_mutex_unlock(&LOCK_open);
 
2857
  }
 
2858
  return(res);
 
2859
}
 
2860
 
 
2861
 
 
2862
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2863
{
 
2864
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
2865
 
 
2866
  return(mysql_admin_table(session, tables, check_opt,
 
2867
                                "analyze", lock_type, 1, 0, 0, 0,
 
2868
                                &handler::ha_analyze));
 
2869
}
 
2870
 
 
2871
 
 
2872
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2873
{
 
2874
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
2875
 
 
2876
  return(mysql_admin_table(session, tables, check_opt,
 
2877
                                "check", lock_type,
 
2878
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
2879
                                &handler::ha_check));
 
2880
}
 
2881
 
 
2882
 
 
2883
/* table_list should contain just one table */
 
2884
static int
 
2885
mysql_discard_or_import_tablespace(Session *session,
 
2886
                                   TableList *table_list,
 
2887
                                   enum tablespace_op_type tablespace_op)
 
2888
{
 
2889
  Table *table;
 
2890
  bool discard;
 
2891
  int error;
 
2892
 
 
2893
  /*
 
2894
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
 
2895
    ALTER Table
 
2896
  */
 
2897
 
 
2898
  session->set_proc_info("discard_or_import_tablespace");
 
2899
 
 
2900
  discard= test(tablespace_op == DISCARD_TABLESPACE);
 
2901
 
 
2902
 /*
 
2903
   We set this flag so that ha_innobase::open and ::external_lock() do
 
2904
   not complain when we lock the table
 
2905
 */
 
2906
  session->tablespace_op= true;
 
2907
  if (!(table= session->open_ltable(table_list, TL_WRITE)))
 
2908
  {
 
2909
    session->tablespace_op= false;
 
2910
    return -1;
 
2911
  }
 
2912
 
 
2913
  error= table->file->ha_discard_or_import_tablespace(discard);
 
2914
 
 
2915
  session->set_proc_info("end");
 
2916
 
 
2917
  if (error)
 
2918
    goto err;
 
2919
 
 
2920
  /* The ALTER Table is always in its own transaction */
 
2921
  error = ha_autocommit_or_rollback(session, 0);
 
2922
  if (! session->endActiveTransaction())
 
2923
    error=1;
 
2924
  if (error)
 
2925
    goto err;
 
2926
  write_bin_log(session, false, session->query, session->query_length);
 
2927
 
 
2928
err:
 
2929
  ha_autocommit_or_rollback(session, error);
 
2930
  session->tablespace_op=false;
 
2931
 
 
2932
  if (error == 0)
 
2933
  {
 
2934
    session->my_ok();
 
2935
    return 0;
 
2936
  }
 
2937
 
 
2938
  table->file->print_error(error, MYF(0));
 
2939
 
 
2940
  return -1;
 
2941
}
 
2942
 
 
2943
/**
 
2944
  Copy all changes detected by parser to the HA_ALTER_FLAGS
 
2945
*/
 
2946
 
 
2947
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
 
2948
{
 
2949
  uint32_t flags= alter_info->flags;
 
2950
 
 
2951
  if (ALTER_ADD_COLUMN & flags)
 
2952
    alter_flags->set(HA_ADD_COLUMN);
 
2953
  if (ALTER_DROP_COLUMN & flags)
 
2954
    alter_flags->set(HA_DROP_COLUMN);
 
2955
  if (ALTER_RENAME & flags)
 
2956
    alter_flags->set(HA_RENAME_TABLE);
 
2957
  if (ALTER_CHANGE_COLUMN & flags)
 
2958
    alter_flags->set(HA_CHANGE_COLUMN);
 
2959
  if (ALTER_COLUMN_DEFAULT & flags)
 
2960
    alter_flags->set(HA_COLUMN_DEFAULT_VALUE);
 
2961
  if (ALTER_COLUMN_STORAGE & flags)
 
2962
    alter_flags->set(HA_COLUMN_STORAGE);
 
2963
  if (ALTER_COLUMN_FORMAT & flags)
 
2964
    alter_flags->set(HA_COLUMN_FORMAT);
 
2965
  if (ALTER_COLUMN_ORDER & flags)
 
2966
    alter_flags->set(HA_ALTER_COLUMN_ORDER);
 
2967
  if (ALTER_STORAGE & flags)
 
2968
    alter_flags->set(HA_ALTER_STORAGE);
 
2969
  if (ALTER_ROW_FORMAT & flags)
 
2970
    alter_flags->set(HA_ALTER_ROW_FORMAT);
 
2971
  if (ALTER_RECREATE & flags)
 
2972
    alter_flags->set(HA_RECREATE);
 
2973
  if (ALTER_FOREIGN_KEY & flags)
 
2974
    alter_flags->set(HA_ALTER_FOREIGN_KEY);
 
2975
}
 
2976
 
 
2977
 
 
2978
/*
 
2979
  Manages enabling/disabling of indexes for ALTER Table
 
2980
 
 
2981
  SYNOPSIS
 
2982
    alter_table_manage_keys()
 
2983
      table                  Target table
 
2984
      indexes_were_disabled  Whether the indexes of the from table
 
2985
                             were disabled
 
2986
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
 
2987
 
 
2988
  RETURN VALUES
 
2989
    false  OK
 
2990
    true   Error
 
2991
*/
 
2992
 
 
2993
static
 
2994
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
 
2995
                             enum enum_enable_or_disable keys_onoff)
 
2996
{
 
2997
  int error= 0;
 
2998
  switch (keys_onoff) {
 
2999
  case ENABLE:
 
3000
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3001
    break;
 
3002
  case LEAVE_AS_IS:
 
3003
    if (!indexes_were_disabled)
 
3004
      break;
 
3005
    /* fall-through: disabled indexes */
 
3006
  case DISABLE:
 
3007
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3008
  }
 
3009
 
 
3010
  if (error == HA_ERR_WRONG_COMMAND)
 
3011
  {
 
3012
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3013
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3014
                        table->s->table_name.str);
 
3015
    error= 0;
 
3016
  } else if (error)
 
3017
    table->file->print_error(error, MYF(0));
 
3018
 
 
3019
  return(error);
 
3020
}
 
3021
 
 
3022
static int 
 
3023
create_temporary_table(Session *session,
 
3024
                       Table *table,
 
3025
                       char *new_db,
 
3026
                       char *tmp_name,
 
3027
                       HA_CREATE_INFO *create_info,
 
3028
                       Alter_info *alter_info,
 
3029
                       bool db_changed)
 
3030
{
 
3031
  int error;
 
3032
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
 
3033
  StorageEngine *old_db_type, *new_db_type;
 
3034
  old_db_type= table->s->db_type();
 
3035
  new_db_type= create_info->db_type;
 
3036
  /*
 
3037
    Handling of symlinked tables:
 
3038
    If no rename:
 
3039
      Create new data file and index file on the same disk as the
 
3040
      old data and index files.
 
3041
      Copy data.
 
3042
      Rename new data file over old data file and new index file over
 
3043
      old index file.
 
3044
      Symlinks are not changed.
 
3045
 
 
3046
   If rename:
 
3047
      Create new data file and index file on the same disk as the
 
3048
      old data and index files.  Create also symlinks to point at
 
3049
      the new tables.
 
3050
      Copy data.
 
3051
      At end, rename intermediate tables, and symlinks to intermediate
 
3052
      table, to final table name.
 
3053
      Remove old table and old symlinks
 
3054
 
 
3055
    If rename is made to another database:
 
3056
      Create new tables in new database.
 
3057
      Copy data.
 
3058
      Remove old table and symlinks.
 
3059
  */
 
3060
  if (db_changed)               // Ignore symlink if db changed
 
3061
  {
 
3062
    if (create_info->index_file_name)
 
3063
    {
 
3064
      /* Fix index_file_name to have 'tmp_name' as basename */
 
3065
      strcpy(index_file, tmp_name);
 
3066
      create_info->index_file_name=fn_same(index_file,
 
3067
                                           create_info->index_file_name,
 
3068
                                           1);
 
3069
    }
 
3070
    if (create_info->data_file_name)
 
3071
    {
 
3072
      /* Fix data_file_name to have 'tmp_name' as basename */
 
3073
      strcpy(data_file, tmp_name);
 
3074
      create_info->data_file_name=fn_same(data_file,
 
3075
                                          create_info->data_file_name,
 
3076
                                          1);
 
3077
    }
 
3078
  }
 
3079
  else
 
3080
    create_info->data_file_name=create_info->index_file_name=0;
 
3081
 
 
3082
  /*
 
3083
    Create a table with a temporary name.
 
3084
    We don't log the statement, it will be logged later.
 
3085
  */
 
3086
  drizzled::message::Table table_proto;
 
3087
  table_proto.set_name(tmp_name);
 
3088
  table_proto.set_type(drizzled::message::Table::TEMPORARY);
 
3089
 
 
3090
  drizzled::message::Table::StorageEngine *protoengine;
 
3091
  protoengine= table_proto.mutable_engine();
 
3092
  protoengine->set_name(new_db_type->getName());
 
3093
 
 
3094
  error= mysql_create_table(session, new_db, tmp_name,
 
3095
                            create_info, &table_proto, alter_info, 1, 0);
 
3096
 
 
3097
  return(error);
 
3098
}
 
3099
 
 
3100
 
 
3101
/**
 
3102
  Prepare column and key definitions for CREATE TABLE in ALTER Table.
 
3103
 
 
3104
  This function transforms parse output of ALTER Table - lists of
 
3105
  columns and keys to add, drop or modify into, essentially,
 
3106
  CREATE TABLE definition - a list of columns and keys of the new
 
3107
  table. While doing so, it also performs some (bug not all)
 
3108
  semantic checks.
 
3109
 
 
3110
  This function is invoked when we know that we're going to
 
3111
  perform ALTER Table via a temporary table -- i.e. fast ALTER Table
 
3112
  is not possible, perhaps because the ALTER statement contains
 
3113
  instructions that require change in table data, not only in
 
3114
  table definition or indexes.
 
3115
 
 
3116
  @param[in,out]  session         thread handle. Used as a memory pool
 
3117
                              and source of environment information.
 
3118
  @param[in]      table       the source table, open and locked
 
3119
                              Used as an interface to the storage engine
 
3120
                              to acquire additional information about
 
3121
                              the original table.
 
3122
  @param[in,out]  create_info A blob with CREATE/ALTER Table
 
3123
                              parameters
 
3124
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
 
3125
                              Originally create_info was used only in
 
3126
                              CREATE TABLE and alter_info only in ALTER Table.
 
3127
                              But since ALTER might end-up doing CREATE,
 
3128
                              this distinction is gone and we just carry
 
3129
                              around two structures.
 
3130
 
 
3131
  @return
 
3132
    Fills various create_info members based on information retrieved
 
3133
    from the storage engine.
 
3134
    Sets create_info->varchar if the table has a VARCHAR column.
 
3135
    Prepares alter_info->create_list and alter_info->key_list with
 
3136
    columns and keys of the new table.
 
3137
  @retval true   error, out of memory or a semantical error in ALTER
 
3138
                 Table instructions
 
3139
  @retval false  success
 
3140
*/
 
3141
 
 
3142
static bool
 
3143
mysql_prepare_alter_table(Session *session, Table *table,
 
3144
                          HA_CREATE_INFO *create_info,
 
3145
                          Alter_info *alter_info)
 
3146
{
 
3147
  /* New column definitions are added here */
 
3148
  List<CreateField> new_create_list;
 
3149
  /* New key definitions are added here */
 
3150
  List<Key> new_key_list;
 
3151
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
 
3152
  List_iterator<CreateField> def_it(alter_info->create_list);
 
3153
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
 
3154
  List_iterator<Key> key_it(alter_info->key_list);
 
3155
  List_iterator<CreateField> find_it(new_create_list);
 
3156
  List_iterator<CreateField> field_it(new_create_list);
 
3157
  List<Key_part_spec> key_parts;
 
3158
  uint32_t db_create_options= (table->s->db_create_options
 
3159
                           & ~(HA_OPTION_PACK_RECORD));
 
3160
  uint32_t used_fields= create_info->used_fields;
 
3161
  KEY *key_info=table->key_info;
 
3162
  bool rc= true;
 
3163
 
 
3164
 
 
3165
  create_info->varchar= false;
 
3166
  /* Let new create options override the old ones */
 
3167
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
 
3168
    create_info->min_rows= table->s->min_rows;
 
3169
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
 
3170
    create_info->max_rows= table->s->max_rows;
 
3171
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
 
3172
    create_info->avg_row_length= table->s->avg_row_length;
 
3173
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
3174
    create_info->block_size= table->s->block_size;
 
3175
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
3176
    create_info->default_table_charset= table->s->table_charset;
 
3177
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
3178
    {
 
3179
    /* Table has an autoincrement, copy value to new table */
 
3180
    table->file->info(HA_STATUS_AUTO);
 
3181
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
 
3182
  }
 
3183
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
3184
    create_info->key_block_size= table->s->key_block_size;
 
3185
 
 
3186
  table->restoreRecordAsDefault();     // Empty record for DEFAULT
 
3187
  CreateField *def;
 
3188
 
 
3189
    /*
 
3190
    First collect all fields from table which isn't in drop_list
 
3191
    */
 
3192
  Field **f_ptr,*field;
 
3193
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
 
3194
  {
 
3195
    /* Check if field should be dropped */
 
3196
    Alter_drop *drop;
 
3197
    drop_it.rewind();
 
3198
    while ((drop=drop_it++))
 
3199
    {
 
3200
      if (drop->type == Alter_drop::COLUMN &&
 
3201
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
 
3202
      {
 
3203
        /* Reset auto_increment value if it was dropped */
 
3204
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
3205
            !(used_fields & HA_CREATE_USED_AUTO))
 
3206
        {
 
3207
          create_info->auto_increment_value=0;
 
3208
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
3209
        }
 
3210
        break;
 
3211
      }
 
3212
    }
 
3213
    if (drop)
 
3214
    {
 
3215
      drop_it.remove();
 
3216
      continue;
 
3217
    }
 
3218
    
 
3219
    /* Mark that we will read the field */
 
3220
    field->setReadSet();
 
3221
 
 
3222
    /* Check if field is changed */
 
3223
    def_it.rewind();
 
3224
    while ((def=def_it++))
 
3225
    {
 
3226
      if (def->change &&
 
3227
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
3228
        break;
 
3229
    }
 
3230
    if (def)
 
3231
    {                                           // Field is changed
 
3232
      def->field=field;
 
3233
      if (!def->after)
 
3234
      {
 
3235
        new_create_list.push_back(def);
 
3236
        def_it.remove();
 
3237
      }
 
3238
    }
 
3239
    else
 
3240
    {
 
3241
      /*
 
3242
        This field was not dropped and not changed, add it to the list
 
3243
        for the new table.
 
3244
      */
 
3245
      def= new CreateField(field, field);
 
3246
      new_create_list.push_back(def);
 
3247
      alter_it.rewind();                        // Change default if ALTER
 
3248
      Alter_column *alter;
 
3249
      while ((alter=alter_it++))
 
3250
      {
 
3251
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
3252
          break;
 
3253
      }
 
3254
      if (alter)
 
3255
      {
 
3256
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
 
3257
        {
 
3258
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
3259
          goto err;
 
3260
        }
 
3261
        if ((def->def=alter->def))              // Use new default
 
3262
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
 
3263
        else
 
3264
          def->flags|= NO_DEFAULT_VALUE_FLAG;
 
3265
        alter_it.remove();
 
3266
      }
 
3267
    }
 
3268
  }
 
3269
  def_it.rewind();
 
3270
  while ((def=def_it++))                        // Add new columns
 
3271
  {
 
3272
    if (def->change && ! def->field)
 
3273
    {
 
3274
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
3275
      goto err;
 
3276
    }
 
3277
    /*
 
3278
      Check that the DATE/DATETIME not null field we are going to add is
 
3279
      either has a default value or the '0000-00-00' is allowed by the
 
3280
      set sql mode.
 
3281
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
3282
      flag to allow ALTER Table only if the table to be altered is empty.
 
3283
    */
 
3284
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
3285
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
3286
        !alter_info->datetime_field &&
 
3287
        !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
3288
        session->variables.sql_mode & MODE_NO_ZERO_DATE)
 
3289
    {
 
3290
      alter_info->datetime_field= def;
 
3291
      alter_info->error_if_not_empty= true;
 
3292
    }
 
3293
    if (!def->after)
 
3294
      new_create_list.push_back(def);
 
3295
    else if (def->after == first_keyword)
 
3296
      new_create_list.push_front(def);
 
3297
    else
 
3298
    {
 
3299
      CreateField *find;
 
3300
      find_it.rewind();
 
3301
      while ((find=find_it++))                  // Add new columns
 
3302
      {
 
3303
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
3304
          break;
 
3305
      }
 
3306
      if (!find)
 
3307
      {
 
3308
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
3309
        goto err;
 
3310
      }
 
3311
      find_it.after(def);                       // Put element after this
 
3312
      /*
 
3313
        XXX: hack for Bug#28427.
 
3314
        If column order has changed, force OFFLINE ALTER Table
 
3315
        without querying engine capabilities.  If we ever have an
 
3316
        engine that supports online ALTER Table CHANGE COLUMN
 
3317
        <name> AFTER <name1> (Falcon?), this fix will effectively
 
3318
        disable the capability.
 
3319
        TODO: detect the situation in compare_tables, behave based
 
3320
        on engine capabilities.
 
3321
      */
 
3322
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
3323
      {
 
3324
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
3325
        goto err;
 
3326
      }
 
3327
      alter_info->build_method= HA_BUILD_OFFLINE;
 
3328
    }
 
3329
  }
 
3330
  if (alter_info->alter_list.elements)
 
3331
  {
 
3332
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
3333
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
3334
    goto err;
 
3335
  }
 
3336
  if (!new_create_list.elements)
 
3337
  {
 
3338
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
 
3339
               MYF(0));
 
3340
    goto err;
 
3341
  }
 
3342
 
 
3343
  /*
 
3344
    Collect all keys which isn't in drop list. Add only those
 
3345
    for which some fields exists.
 
3346
  */
 
3347
 
 
3348
  for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
 
3349
  {
 
3350
    char *key_name= key_info->name;
 
3351
    Alter_drop *drop;
 
3352
    drop_it.rewind();
 
3353
    while ((drop=drop_it++))
 
3354
    {
 
3355
      if (drop->type == Alter_drop::KEY &&
 
3356
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
3357
        break;
 
3358
    }
 
3359
    if (drop)
 
3360
    {
 
3361
      drop_it.remove();
 
3362
      continue;
 
3363
    }
 
3364
 
 
3365
    KEY_PART_INFO *key_part= key_info->key_part;
 
3366
    key_parts.empty();
 
3367
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
3368
    {
 
3369
      if (!key_part->field)
 
3370
        continue;                               // Wrong field (from UNIREG)
 
3371
      const char *key_part_name=key_part->field->field_name;
 
3372
      CreateField *cfield;
 
3373
      field_it.rewind();
 
3374
      while ((cfield=field_it++))
 
3375
      {
 
3376
        if (cfield->change)
 
3377
        {
 
3378
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
3379
                             cfield->change))
 
3380
            break;
 
3381
        }
 
3382
        else if (!my_strcasecmp(system_charset_info,
 
3383
                                key_part_name, cfield->field_name))
 
3384
          break;
 
3385
      }
 
3386
      if (!cfield)
 
3387
        continue;                               // Field is removed
 
3388
      uint32_t key_part_length=key_part->length;
 
3389
      if (cfield->field)                        // Not new field
 
3390
      {
 
3391
        /*
 
3392
          If the field can't have only a part used in a key according to its
 
3393
          new type, or should not be used partially according to its
 
3394
          previous type, or the field length is less than the key part
 
3395
          length, unset the key part length.
 
3396
 
 
3397
          We also unset the key part length if it is the same as the
 
3398
          old field's length, so the whole new field will be used.
 
3399
 
 
3400
          BLOBs may have cfield->length == 0, which is why we test it before
 
3401
          checking whether cfield->length < key_part_length (in chars).
 
3402
         */
 
3403
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
3404
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
3405
            (cfield->field->field_length == key_part_length &&
 
3406
             !f_is_blob(key_part->key_type)) ||
 
3407
            (cfield->length && (cfield->length < key_part_length /
 
3408
                                key_part->field->charset()->mbmaxlen)))
 
3409
          key_part_length= 0;                   // Use whole field
 
3410
      }
 
3411
      key_part_length /= key_part->field->charset()->mbmaxlen;
 
3412
      key_parts.push_back(new Key_part_spec(cfield->field_name,
 
3413
                                            strlen(cfield->field_name),
 
3414
                                            key_part_length));
 
3415
    }
 
3416
    if (key_parts.elements)
 
3417
    {
 
3418
      KEY_CREATE_INFO key_create_info;
 
3419
      Key *key;
 
3420
      enum Key::Keytype key_type;
 
3421
      memset(&key_create_info, 0, sizeof(key_create_info));
 
3422
 
 
3423
      key_create_info.algorithm= key_info->algorithm;
 
3424
      if (key_info->flags & HA_USES_BLOCK_SIZE)
 
3425
        key_create_info.block_size= key_info->block_size;
 
3426
      if (key_info->flags & HA_USES_COMMENT)
 
3427
        key_create_info.comment= key_info->comment;
 
3428
 
 
3429
      if (key_info->flags & HA_NOSAME)
 
3430
      {
 
3431
        if (is_primary_key_name(key_name))
 
3432
          key_type= Key::PRIMARY;
 
3433
        else
 
3434
          key_type= Key::UNIQUE;
 
3435
      }
 
3436
      else
 
3437
        key_type= Key::MULTIPLE;
 
3438
 
 
3439
      key= new Key(key_type, key_name, strlen(key_name),
 
3440
                   &key_create_info,
 
3441
                   test(key_info->flags & HA_GENERATED_KEY),
 
3442
                   key_parts);
 
3443
      new_key_list.push_back(key);
 
3444
    }
 
3445
  }
 
3446
  {
 
3447
    Key *key;
 
3448
    while ((key=key_it++))                      // Add new keys
 
3449
    {
 
3450
      if (key->type == Key::FOREIGN_KEY &&
 
3451
          ((Foreign_key *)key)->validate(new_create_list))
 
3452
        goto err;
 
3453
      if (key->type != Key::FOREIGN_KEY)
 
3454
        new_key_list.push_back(key);
 
3455
      if (key->name.str && is_primary_key_name(key->name.str))
 
3456
      {
 
3457
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
3458
        goto err;
 
3459
      }
 
3460
    }
 
3461
  }
 
3462
 
 
3463
  if (alter_info->drop_list.elements)
 
3464
  {
 
3465
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
3466
             alter_info->drop_list.head()->name);
 
3467
    goto err;
 
3468
  }
 
3469
  if (alter_info->alter_list.elements)
 
3470
  {
 
3471
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
3472
             alter_info->alter_list.head()->name);
 
3473
    goto err;
 
3474
  }
 
3475
 
 
3476
  if (!create_info->comment.str)
 
3477
  {
 
3478
    create_info->comment.str= table->s->comment.str;
 
3479
    create_info->comment.length= table->s->comment.length;
 
3480
  }
 
3481
 
 
3482
  table->file->update_create_info(create_info);
 
3483
  if ((create_info->table_options &
 
3484
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
 
3485
      (used_fields & HA_CREATE_USED_PACK_KEYS))
 
3486
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
 
3487
  if (create_info->table_options &
 
3488
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
 
3489
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
 
3490
  if (create_info->table_options &
 
3491
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
 
3492
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
 
3493
                          HA_OPTION_NO_DELAY_KEY_WRITE);
 
3494
  create_info->table_options|= db_create_options;
 
3495
 
 
3496
  if (table->s->tmp_table)
 
3497
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
3498
 
 
3499
  rc= false;
 
3500
  alter_info->create_list.swap(new_create_list);
 
3501
  alter_info->key_list.swap(new_key_list);
 
3502
err:
 
3503
  return(rc);
 
3504
}
 
3505
 
 
3506
 
 
3507
/*
 
3508
  Alter table
 
3509
 
 
3510
  SYNOPSIS
 
3511
    mysql_alter_table()
 
3512
      session              Thread handle
 
3513
      new_db           If there is a RENAME clause
 
3514
      new_name         If there is a RENAME clause
 
3515
      create_info      Information from the parsing phase about new
 
3516
                       table properties.
 
3517
      table_list       The table to change.
 
3518
      alter_info       Lists of fields, keys to be changed, added
 
3519
                       or dropped.
 
3520
      order_num        How many order_st BY fields has been specified.
 
3521
      order            List of fields to order_st BY.
 
3522
      ignore           Whether we have ALTER IGNORE Table
 
3523
 
 
3524
  DESCRIPTION
 
3525
    This is a veery long function and is everything but the kitchen sink :)
 
3526
    It is used to alter a table and not only by ALTER Table but also
 
3527
    CREATE|DROP INDEX are mapped on this function.
 
3528
 
 
3529
    When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
 
3530
    or both, then this function short cuts its operation by renaming
 
3531
    the table and/or enabling/disabling the keys. In this case, the FRM is
 
3532
    not changed, directly by mysql_alter_table. However, if there is a
 
3533
    RENAME + change of a field, or an index, the short cut is not used.
 
3534
    See how `create_list` is used to generate the new FRM regarding the
 
3535
    structure of the fields. The same is done for the indices of the table.
 
3536
 
 
3537
    Important is the fact, that this function tries to do as little work as
 
3538
    possible, by finding out whether a intermediate table is needed to copy
 
3539
    data into and when finishing the altering to use it as the original table.
 
3540
    For this reason the function compare_tables() is called, which decides
 
3541
    based on all kind of data how similar are the new and the original
 
3542
    tables.
 
3543
 
 
3544
  RETURN VALUES
 
3545
    false  OK
 
3546
    true   Error
 
3547
*/
 
3548
 
 
3549
bool mysql_alter_table(Session *session, char *new_db, char *new_name,
 
3550
                       HA_CREATE_INFO *create_info,
 
3551
                       TableList *table_list,
 
3552
                       Alter_info *alter_info,
 
3553
                       uint32_t order_num, order_st *order, bool ignore)
 
3554
{
 
3555
  Table *table, *new_table=0, *name_lock= 0;;
 
3556
  string new_name_str;
 
3557
  int error= 0;
 
3558
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
 
3559
  char new_alias_buff[FN_REFLEN], *table_name, *db;
 
3560
  const char *new_alias;
 
3561
  char path[FN_REFLEN];
 
3562
  ha_rows copied= 0,deleted= 0;
 
3563
  StorageEngine *old_db_type, *new_db_type, *save_old_db_type;
 
3564
 
 
3565
  new_name_buff[0]= '\0';
 
3566
 
 
3567
  if (table_list && table_list->schema_table)
 
3568
  {
 
3569
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
3570
    return true;
 
3571
  }
 
3572
 
 
3573
  /*
 
3574
    Assign variables table_name, new_name, db, new_db, path
 
3575
    to simplify further comparisons: we want to see if it's a RENAME
 
3576
    later just by comparing the pointers, avoiding the need for strcmp.
 
3577
  */
 
3578
  session->set_proc_info("init");
 
3579
  table_name= table_list->table_name;
 
3580
  db=table_list->db;
 
3581
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
 
3582
    new_db= db;
 
3583
  build_table_filename(path, sizeof(path), db, table_name, false);
 
3584
 
 
3585
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
3586
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
3587
    /* Conditionally writes to binlog. */
 
3588
    return(mysql_discard_or_import_tablespace(session,table_list,
 
3589
                                              alter_info->tablespace_op));
 
3590
  ostringstream oss;
 
3591
  oss << drizzle_data_home << "/" << db << "/" << table_name;
 
3592
 
 
3593
  (void) unpack_filename(new_name_buff, oss.str().c_str());
 
3594
  /*
 
3595
    If this is just a rename of a view, short cut to the
 
3596
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
3597
    2) unlock LOCK_open.
 
3598
    This is a copy-paste added to make sure
 
3599
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
 
3600
    as an independent branch in mysql_execute_command. The need
 
3601
    for a copy-paste arose because the main code flow of ALTER Table
 
3602
    ... RENAME tries to use open_ltable, which does not work for views
 
3603
    (open_ltable was never modified to merge table lists of child tables
 
3604
    into the main table list, like open_tables does).
 
3605
    This code is wrong and will be removed, please do not copy.
 
3606
  */
 
3607
 
 
3608
  if (!(table= session->open_ltable(table_list, TL_WRITE_ALLOW_READ)))
 
3609
    return true;
 
3610
  table->use_all_columns();
 
3611
 
 
3612
  /* Check that we are not trying to rename to an existing table */
 
3613
  if (new_name)
 
3614
  {
 
3615
    strcpy(new_name_buff, new_name);
 
3616
    strcpy(new_alias_buff, new_name);
 
3617
    new_alias= new_alias_buff;
 
3618
 
 
3619
    my_casedn_str(files_charset_info, new_name_buff);
 
3620
    new_alias= new_name;                        // Create lower case table name
 
3621
    my_casedn_str(files_charset_info, new_name);
 
3622
 
 
3623
    if (new_db == db &&
 
3624
        !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
3625
    {
 
3626
      /*
 
3627
        Source and destination table names are equal: make later check
 
3628
        easier.
 
3629
      */
 
3630
      new_alias= new_name= table_name;
 
3631
    }
 
3632
    else
 
3633
    {
 
3634
      if (table->s->tmp_table != NO_TMP_TABLE)
 
3635
      {
 
3636
        if (session->find_temporary_table(new_db, new_name_buff))
 
3637
        {
 
3638
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
3639
          return true;
 
3640
        }
 
3641
      }
 
3642
      else
 
3643
      {
 
3644
        if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
 
3645
          return true;
 
3646
 
 
3647
        if (!name_lock)
 
3648
        {
 
3649
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
3650
          return true;
 
3651
        }
 
3652
 
 
3653
        build_table_filename(new_name_buff, sizeof(new_name_buff),
 
3654
                             new_db, new_name_buff, false);
 
3655
        if (table_proto_exists(new_name_buff)==EEXIST)
 
3656
        {
 
3657
          /* Table will be closed by Session::executeCommand() */
 
3658
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
3659
          goto err;
 
3660
        }
 
3661
      }
 
3662
    }
 
3663
  }
 
3664
  else
 
3665
  {
 
3666
    new_alias= table_name;
 
3667
    new_name= table_name;
 
3668
  }
 
3669
 
 
3670
  old_db_type= table->s->db_type();
 
3671
  if (!create_info->db_type)
 
3672
  {
 
3673
    create_info->db_type= old_db_type;
 
3674
  }
 
3675
 
 
3676
  if(table->s->tmp_table != NO_TMP_TABLE)
 
3677
    create_info->options|= HA_LEX_CREATE_TMP_TABLE;
 
3678
 
 
3679
  if (check_engine(session, new_name, create_info))
 
3680
    goto err;
 
3681
  new_db_type= create_info->db_type;
 
3682
 
 
3683
  if (new_db_type != old_db_type &&
 
3684
      !table->file->can_switch_engines())
 
3685
  {
 
3686
    assert(0);
 
3687
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
 
3688
    goto err;
 
3689
  }
 
3690
 
 
3691
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
3692
    create_info->row_type= table->s->row_type;
 
3693
 
 
3694
  if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
 
3695
      new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
 
3696
  {
 
3697
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
3698
    goto err;
 
3699
  }
 
3700
 
 
3701
  session->set_proc_info("setup");
 
3702
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
 
3703
      !table->s->tmp_table) // no need to touch frm
 
3704
  {
 
3705
    switch (alter_info->keys_onoff) {
 
3706
    case LEAVE_AS_IS:
 
3707
      break;
 
3708
    case ENABLE:
 
3709
      /*
 
3710
        wait_while_table_is_used() ensures that table being altered is
 
3711
        opened only by this thread and that Table::TableShare::version
 
3712
        of Table object corresponding to this table is 0.
 
3713
        The latter guarantees that no DML statement will open this table
 
3714
        until ALTER Table finishes (i.e. until close_thread_tables())
 
3715
        while the fact that the table is still open gives us protection
 
3716
        from concurrent DDL statements.
 
3717
      */
 
3718
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
3719
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
3720
      pthread_mutex_unlock(&LOCK_open);
 
3721
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3722
      /* COND_refresh will be signaled in close_thread_tables() */
 
3723
      break;
 
3724
    case DISABLE:
 
3725
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
3726
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
3727
      pthread_mutex_unlock(&LOCK_open);
 
3728
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
3729
      /* COND_refresh will be signaled in close_thread_tables() */
 
3730
      break;
 
3731
    default:
 
3732
      assert(false);
 
3733
      error= 0;
 
3734
      break;
 
3735
    }
 
3736
    if (error == HA_ERR_WRONG_COMMAND)
 
3737
    {
 
3738
      error= 0;
 
3739
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3740
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3741
                          table->alias);
 
3742
    }
 
3743
 
 
3744
    pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
 
3745
    /*
 
3746
      Unlike to the above case close_cached_table() below will remove ALL
 
3747
      instances of Table from table cache (it will also remove table lock
 
3748
      held by this thread). So to make actual table renaming and writing
 
3749
      to binlog atomic we have to put them into the same critical section
 
3750
      protected by LOCK_open mutex. This also removes gap for races between
 
3751
      access() and mysql_rename_table() calls.
 
3752
    */
 
3753
 
 
3754
    if (!error && (new_name != table_name || new_db != db))
 
3755
    {
 
3756
      session->set_proc_info("rename");
 
3757
      /*
 
3758
        Then do a 'simple' rename of the table. First we need to close all
 
3759
        instances of 'source' table.
 
3760
      */
 
3761
      session->close_cached_table(table);
 
3762
      /*
 
3763
        Then, we want check once again that target table does not exist.
 
3764
        Actually the order of these two steps does not matter since
 
3765
        earlier we took name-lock on the target table, so we do them
 
3766
        in this particular order only to be consistent with 5.0, in which
 
3767
        we don't take this name-lock and where this order really matters.
 
3768
        TODO: Investigate if we need this access() check at all.
 
3769
      */
 
3770
      if (table_proto_exists(new_name)==EEXIST)
 
3771
      {
 
3772
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
3773
        error= -1;
 
3774
      }
 
3775
      else
 
3776
      {
 
3777
        *fn_ext(new_name)=0;
 
3778
        if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
 
3779
          error= -1;
 
3780
        else if (0)
 
3781
        {
 
3782
          mysql_rename_table(old_db_type, new_db, new_alias, db,
 
3783
                             table_name, 0);
 
3784
          error= -1;
 
3785
        }
 
3786
      }
 
3787
    }
 
3788
 
 
3789
    if (error == HA_ERR_WRONG_COMMAND)
 
3790
    {
 
3791
      error= 0;
 
3792
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
3793
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
3794
                          table->alias);
 
3795
    }
 
3796
 
 
3797
    if (!error)
 
3798
    {
 
3799
      write_bin_log(session, true, session->query, session->query_length);
 
3800
      session->my_ok();
 
3801
  }
 
3802
    else if (error > 0)
 
3803
  {
 
3804
      table->file->print_error(error, MYF(0));
 
3805
      error= -1;
 
3806
    }
2151
3807
    if (name_lock)
2152
 
    {
2153
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2154
3808
      session->unlink_open_table(name_lock);
2155
 
    }
2156
 
  }
2157
 
 
2158
 
  if (table_exists)
2159
 
  {
2160
 
    if (is_if_not_exists)
 
3809
    pthread_mutex_unlock(&LOCK_open);
 
3810
    table_list->table= NULL;                    // For query cache
 
3811
    return(error);
 
3812
  }
 
3813
 
 
3814
  /* We have to do full alter table. */
 
3815
 
 
3816
    /*
 
3817
    If the old table had partitions and we are doing ALTER Table ...
 
3818
    engine= <new_engine>, the new table must preserve the original
 
3819
    partitioning. That means that the new engine is still the
 
3820
    partitioning engine, not the engine specified in the parser.
 
3821
    This is discovered  in prep_alter_part_table, which in such case
 
3822
    updates create_info->db_type.
 
3823
    Now we need to update the stack copy of create_info->db_type,
 
3824
    as otherwise we won't be able to correctly move the files of the
 
3825
    temporary table to the result table files.
 
3826
  */
 
3827
  new_db_type= create_info->db_type;
 
3828
 
 
3829
  if (mysql_prepare_alter_table(session, table, create_info, alter_info))
 
3830
      goto err;
 
3831
 
 
3832
  set_table_default_charset(create_info, db);
 
3833
 
 
3834
  alter_info->build_method= HA_BUILD_OFFLINE;
 
3835
 
 
3836
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX,
 
3837
           (unsigned long)current_pid, session->thread_id);
 
3838
  /* Safety fix for innodb */
 
3839
  my_casedn_str(files_charset_info, tmp_name);
 
3840
 
 
3841
 
 
3842
  /* Create a temporary table with the new format */
 
3843
  if ((error= create_temporary_table(session, table, new_db, tmp_name,
 
3844
                                     create_info, alter_info,
 
3845
                                     !strcmp(db, new_db))))
 
3846
  {
 
3847
    goto err;
 
3848
  }
 
3849
 
 
3850
  /* Open the table so we need to copy the data to it. */
 
3851
  if (table->s->tmp_table)
 
3852
  {
 
3853
    TableList tbl;
 
3854
    tbl.db= new_db;
 
3855
    tbl.alias= tmp_name;
 
3856
    tbl.table_name= tmp_name;
 
3857
 
 
3858
    /* Table is in session->temporary_tables */
 
3859
    new_table= session->open_table(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
 
3860
  }
 
3861
  else
 
3862
  {
 
3863
    char tmp_path[FN_REFLEN];
 
3864
    /* table is a normal table: Create temporary table in same directory */
 
3865
    build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
 
3866
    /* Open our intermediate table */
 
3867
    new_table= open_temporary_table(session, tmp_path, new_db, tmp_name, 0, OTM_OPEN);
 
3868
  }
 
3869
 
 
3870
  if (new_table == NULL)
 
3871
    goto err1;
 
3872
 
 
3873
  /* Copy the data if necessary. */
 
3874
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
 
3875
  session->cuted_fields=0L;
 
3876
  session->set_proc_info("copy to tmp table");
 
3877
  copied= deleted= 0;
 
3878
 
 
3879
  assert(new_table);
 
3880
 
 
3881
  /* We don't want update TIMESTAMP fields during ALTER Table. */
 
3882
  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
3883
  new_table->next_number_field=new_table->found_next_number_field;
 
3884
  error= copy_data_between_tables(table, new_table,
 
3885
                                  alter_info->create_list, ignore,
 
3886
                                  order_num, order, &copied, &deleted,
 
3887
                                  alter_info->keys_onoff,
 
3888
                                  alter_info->error_if_not_empty);
 
3889
 
 
3890
  /* We must not ignore bad input! */;
 
3891
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
3892
 
 
3893
  if (table->s->tmp_table != NO_TMP_TABLE)
 
3894
  {
 
3895
    /* We changed a temporary table */
 
3896
    if (error)
 
3897
      goto err1;
 
3898
    /* Close lock if this is a transactional table */
 
3899
    if (session->lock)
 
3900
    {
 
3901
      mysql_unlock_tables(session, session->lock);
 
3902
      session->lock=0;
 
3903
    }
 
3904
    /* Remove link to old table and rename the new one */
 
3905
    session->close_temporary_table(table, true, true);
 
3906
    /* Should pass the 'new_name' as we store table name in the cache */
 
3907
    if (rename_temporary_table(new_table, new_db, new_name))
 
3908
      goto err1;
 
3909
    goto end_temporary;
 
3910
  }
 
3911
 
 
3912
  if (new_table)
 
3913
  {
 
3914
    /*
 
3915
      Close the intermediate table that will be the new table.
 
3916
      Note that MERGE tables do not have their children attached here.
 
3917
    */
 
3918
    intern_close_table(new_table);
 
3919
    free(new_table);
 
3920
  }
 
3921
  pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
 
3922
  if (error)
 
3923
  {
 
3924
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3925
    pthread_mutex_unlock(&LOCK_open);
 
3926
    goto err;
 
3927
  }
 
3928
 
 
3929
  /*
 
3930
    Data is copied. Now we:
 
3931
    1) Wait until all other threads close old version of table.
 
3932
    2) Close instances of table open by this thread and replace them
 
3933
       with exclusive name-locks.
 
3934
    3) Rename the old table to a temp name, rename the new one to the
 
3935
       old name.
 
3936
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
3937
       we reopen new version of table.
 
3938
    5) Write statement to the binary log.
 
3939
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
3940
       remove name-locks from list of open tables and table cache.
 
3941
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
3942
       call to remove name-locks from table cache and list of open table.
 
3943
  */
 
3944
 
 
3945
  session->set_proc_info("rename result table");
 
3946
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX,
 
3947
           (unsigned long)current_pid, session->thread_id);
 
3948
  my_casedn_str(files_charset_info, old_name);
 
3949
 
 
3950
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
3951
  session->close_data_files_and_morph_locks(db, table_name);
 
3952
 
 
3953
  error=0;
 
3954
  save_old_db_type= old_db_type;
 
3955
 
 
3956
  /*
 
3957
    This leads to the storage engine (SE) not being notified for renames in
 
3958
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
3959
    more. If we have an intermediate table, then we notify the SE that
 
3960
    it should become the actual table. Later, we will recycle the old table.
 
3961
    However, in case of ALTER Table RENAME there might be no intermediate
 
3962
    table. This is when the old and new tables are compatible, according to
 
3963
    compare_table(). Then, we need one additional call to
 
3964
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
3965
    actual rename in the SE and the FRM is not touched. Note that, if the
 
3966
    table is renamed and the SE is also changed, then an intermediate table
 
3967
    is created and the additional call will not take place.
 
3968
  */
 
3969
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
 
3970
                         FN_TO_IS_TMP))
 
3971
  {
 
3972
    error=1;
 
3973
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3974
  }
 
3975
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
 
3976
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
 
3977
  {
 
3978
    /* Try to get everything back. */
 
3979
    error= 1;
 
3980
    quick_rm_table(new_db_type, new_db, new_alias, false);
 
3981
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
3982
    mysql_rename_table(old_db_type, db, old_name, db, table_name,
 
3983
                       FN_FROM_IS_TMP);
 
3984
  }
 
3985
 
 
3986
  if (error)
 
3987
  {
 
3988
    /* This shouldn't happen. But let us play it safe. */
 
3989
    goto err_with_placeholders;
 
3990
  }
 
3991
 
 
3992
  quick_rm_table(old_db_type, db, old_name, true);
 
3993
 
 
3994
  pthread_mutex_unlock(&LOCK_open);
 
3995
 
 
3996
  session->set_proc_info("end");
 
3997
 
 
3998
  write_bin_log(session, true, session->query, session->query_length);
 
3999
 
 
4000
  if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
 
4001
  {
 
4002
    /*
 
4003
      For the alter table to be properly flushed to the logs, we
 
4004
      have to open the new table.  If not, we get a problem on server
 
4005
      shutdown. But we do not need to attach MERGE children.
 
4006
    */
 
4007
    char table_path[FN_REFLEN];
 
4008
    Table *t_table;
 
4009
    build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
 
4010
    t_table= open_temporary_table(session, table_path, new_db, tmp_name, false, OTM_OPEN);
 
4011
    if (t_table)
 
4012
    {
 
4013
      intern_close_table(t_table);
 
4014
      free(t_table);
 
4015
    }
 
4016
    else
 
4017
      errmsg_printf(ERRMSG_LVL_WARN,
 
4018
                    _("Could not open table %s.%s after rename\n"),
 
4019
                    new_db,table_name);
 
4020
    ha_flush_logs(old_db_type);
 
4021
  }
 
4022
  table_list->table=0;                          // For query cache
 
4023
 
 
4024
end_temporary:
 
4025
  /*
 
4026
   * Field::store() may have called my_error().  If this is 
 
4027
   * the case, we must not send an ok packet, since 
 
4028
   * Diagnostics_area::is_set() will fail an assert.
 
4029
   */
 
4030
  if (! session->is_error())
 
4031
  {
 
4032
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
4033
            (ulong) (copied + deleted), (ulong) deleted,
 
4034
            (ulong) session->cuted_fields);
 
4035
    session->my_ok(copied + deleted, 0L, tmp_name);
 
4036
    session->some_tables_deleted=0;
 
4037
    return false;
 
4038
  }
 
4039
  else
 
4040
  {
 
4041
    /* my_error() was called.  Return true (which means error...) */
 
4042
    return true;
 
4043
  }
 
4044
 
 
4045
err1:
 
4046
  if (new_table)
 
4047
  {
 
4048
    /* close_temporary_table() frees the new_table pointer. */
 
4049
    session->close_temporary_table(new_table, true, true);
 
4050
  }
 
4051
  else
 
4052
    quick_rm_table(new_db_type, new_db, tmp_name, true);
 
4053
 
 
4054
err:
 
4055
  /*
 
4056
    No default value was provided for a DATE/DATETIME field, the
 
4057
    current sql_mode doesn't allow the '0000-00-00' value and
 
4058
    the table to be altered isn't empty.
 
4059
    Report error here.
 
4060
  */
 
4061
  if (alter_info->error_if_not_empty && session->row_count)
 
4062
  {
 
4063
    const char *f_val= 0;
 
4064
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
4065
    switch (alter_info->datetime_field->sql_type)
 
4066
    {
 
4067
      case DRIZZLE_TYPE_DATE:
 
4068
        f_val= "0000-00-00";
 
4069
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
4070
        break;
 
4071
      case DRIZZLE_TYPE_DATETIME:
 
4072
        f_val= "0000-00-00 00:00:00";
 
4073
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
4074
        break;
 
4075
      default:
 
4076
        /* Shouldn't get here. */
 
4077
        assert(0);
 
4078
    }
 
4079
    bool save_abort_on_warning= session->abort_on_warning;
 
4080
    session->abort_on_warning= true;
 
4081
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
4082
                                 f_val, strlength(f_val), t_type,
 
4083
                                 alter_info->datetime_field->field_name);
 
4084
    session->abort_on_warning= save_abort_on_warning;
 
4085
  }
 
4086
  if (name_lock)
 
4087
  {
 
4088
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
 
4089
    session->unlink_open_table(name_lock);
 
4090
    pthread_mutex_unlock(&LOCK_open);
 
4091
  }
 
4092
  return true;
 
4093
 
 
4094
err_with_placeholders:
 
4095
  /*
 
4096
    An error happened while we were holding exclusive name-lock on table
 
4097
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
4098
    from list of open tables list and table cache.
 
4099
  */
 
4100
  session->unlink_open_table(table);
 
4101
  if (name_lock)
 
4102
    session->unlink_open_table(name_lock);
 
4103
  pthread_mutex_unlock(&LOCK_open);
 
4104
  return(true);
 
4105
}
 
4106
/* mysql_alter_table */
 
4107
 
 
4108
static int
 
4109
copy_data_between_tables(Table *from,Table *to,
 
4110
                         List<CreateField> &create,
 
4111
                         bool ignore,
 
4112
                         uint32_t order_num, order_st *order,
 
4113
                         ha_rows *copied,
 
4114
                         ha_rows *deleted,
 
4115
                         enum enum_enable_or_disable keys_onoff,
 
4116
                         bool error_if_not_empty)
 
4117
{
 
4118
  int error;
 
4119
  CopyField *copy,*copy_end;
 
4120
  ulong found_count,delete_count;
 
4121
  Session *session= current_session;
 
4122
  uint32_t length= 0;
 
4123
  SORT_FIELD *sortorder;
 
4124
  READ_RECORD info;
 
4125
  TableList   tables;
 
4126
  List<Item>   fields;
 
4127
  List<Item>   all_fields;
 
4128
  ha_rows examined_rows;
 
4129
  bool auto_increment_field_copied= 0;
 
4130
  ulong save_sql_mode;
 
4131
  uint64_t prev_insert_id;
 
4132
 
 
4133
  /*
 
4134
    Turn off recovery logging since rollback of an alter table is to
 
4135
    delete the new table so there is no need to log the changes to it.
 
4136
 
 
4137
    This needs to be done before external_lock
 
4138
  */
 
4139
  error= ha_enable_transaction(session, false);
 
4140
  if (error)
 
4141
    return -1;
 
4142
 
 
4143
  if (!(copy= new CopyField[to->s->fields]))
 
4144
    return -1;                          /* purecov: inspected */
 
4145
 
 
4146
  if (to->file->ha_external_lock(session, F_WRLCK))
 
4147
    return -1;
 
4148
 
 
4149
  /* We need external lock before we can disable/enable keys */
 
4150
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
4151
 
 
4152
  /* We can abort alter table for any table type */
 
4153
  session->abort_on_warning= !ignore;
 
4154
 
 
4155
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
4156
  to->file->ha_start_bulk_insert(from->file->stats.records);
 
4157
 
 
4158
  save_sql_mode= session->variables.sql_mode;
 
4159
 
 
4160
  List_iterator<CreateField> it(create);
 
4161
  CreateField *def;
 
4162
  copy_end=copy;
 
4163
  for (Field **ptr=to->field ; *ptr ; ptr++)
 
4164
  {
 
4165
    def=it++;
 
4166
    if (def->field)
 
4167
    {
 
4168
      if (*ptr == to->next_number_field)
 
4169
        auto_increment_field_copied= true;
 
4170
 
 
4171
      (copy_end++)->set(*ptr,def->field,0);
 
4172
    }
 
4173
 
 
4174
  }
 
4175
 
 
4176
  found_count=delete_count=0;
 
4177
 
 
4178
  if (order)
 
4179
  {
 
4180
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2161
4181
    {
2162
4182
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
4183
      snprintf(warn_buff, sizeof(warn_buff),
2164
 
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2165
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2166
 
                   ER_TABLE_EXISTS_ERROR,warn_buff);
2167
 
      res= false;
2168
 
    }
2169
 
    else
2170
 
    {
2171
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2172
 
    }
2173
 
  }
2174
 
 
2175
 
  return(res);
2176
 
}
2177
 
 
2178
 
 
2179
 
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2180
 
{
2181
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2182
 
 
2183
 
  return(mysql_admin_table(session, tables, check_opt,
2184
 
                                "analyze", lock_type, true,
2185
 
                                &Cursor::ha_analyze));
2186
 
}
2187
 
 
2188
 
 
2189
 
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2190
 
{
2191
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2192
 
 
2193
 
  return(mysql_admin_table(session, tables, check_opt,
2194
 
                                "check", lock_type,
2195
 
                                false,
2196
 
                                &Cursor::ha_check));
2197
 
}
2198
 
 
2199
 
} /* namespace drizzled */
 
4184
               _("order_st BY ignored because there is a user-defined clustered "
 
4185
                 "index in the table '%-.192s'"),
 
4186
               from->s->table_name.str);
 
4187
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
4188
                   warn_buff);
 
4189
    }
 
4190
    else
 
4191
    {
 
4192
      from->sort.io_cache= new IO_CACHE;
 
4193
      memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
 
4194
 
 
4195
      memset(&tables, 0, sizeof(tables));
 
4196
      tables.table= from;
 
4197
      tables.alias= tables.table_name= from->s->table_name.str;
 
4198
      tables.db= from->s->db.str;
 
4199
      error= 1;
 
4200
 
 
4201
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
4202
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
4203
                      &tables, fields, all_fields, order) ||
 
4204
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
4205
          (from->sort.found_records= filesort(session, from, sortorder, length,
 
4206
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
4207
                                              1, &examined_rows)) ==
 
4208
          HA_POS_ERROR)
 
4209
        goto err;
 
4210
    }
 
4211
  };
 
4212
 
 
4213
  /* Tell handler that we have values for all columns in the to table */
 
4214
  to->use_all_columns();
 
4215
  init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
 
4216
  if (ignore)
 
4217
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
4218
  session->row_count= 0;
 
4219
  to->restoreRecordAsDefault();        // Create empty record
 
4220
  while (!(error=info.read_record(&info)))
 
4221
  {
 
4222
    if (session->killed)
 
4223
    {
 
4224
      session->send_kill_message();
 
4225
      error= 1;
 
4226
      break;
 
4227
    }
 
4228
    session->row_count++;
 
4229
    /* Return error if source table isn't empty. */
 
4230
    if (error_if_not_empty)
 
4231
    {
 
4232
      error= 1;
 
4233
      break;
 
4234
    }
 
4235
    if (to->next_number_field)
 
4236
    {
 
4237
      if (auto_increment_field_copied)
 
4238
        to->auto_increment_field_not_null= true;
 
4239
      else
 
4240
        to->next_number_field->reset();
 
4241
    }
 
4242
 
 
4243
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
4244
    {
 
4245
      copy_ptr->do_copy(copy_ptr);
 
4246
    }
 
4247
    prev_insert_id= to->file->next_insert_id;
 
4248
    error=to->file->ha_write_row(to->record[0]);
 
4249
    to->auto_increment_field_not_null= false;
 
4250
    if (error)
 
4251
    {
 
4252
      if (!ignore ||
 
4253
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
4254
      {
 
4255
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
4256
         {
 
4257
           uint32_t key_nr= to->file->get_dup_key(error);
 
4258
           if ((int) key_nr >= 0)
 
4259
           {
 
4260
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
4261
             if (key_nr == 0 &&
 
4262
                 (to->key_info[0].key_part[0].field->flags &
 
4263
                  AUTO_INCREMENT_FLAG))
 
4264
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
4265
             to->file->print_keydup_error(key_nr, err_msg);
 
4266
             break;
 
4267
           }
 
4268
         }
 
4269
 
 
4270
        to->file->print_error(error,MYF(0));
 
4271
        break;
 
4272
      }
 
4273
      to->file->restore_auto_increment(prev_insert_id);
 
4274
      delete_count++;
 
4275
    }
 
4276
    else
 
4277
      found_count++;
 
4278
  }
 
4279
  end_read_record(&info);
 
4280
  free_io_cache(from);
 
4281
  delete [] copy;                               // This is never 0
 
4282
 
 
4283
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
4284
  {
 
4285
    to->file->print_error(my_errno,MYF(0));
 
4286
    error=1;
 
4287
  }
 
4288
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
4289
 
 
4290
  if (ha_enable_transaction(session, true))
 
4291
  {
 
4292
    error= 1;
 
4293
    goto err;
 
4294
  }
 
4295
 
 
4296
  /*
 
4297
    Ensure that the new table is saved properly to disk so that we
 
4298
    can do a rename
 
4299
  */
 
4300
  if (ha_autocommit_or_rollback(session, 0))
 
4301
    error=1;
 
4302
  if (! session->endActiveTransaction())
 
4303
    error=1;
 
4304
 
 
4305
 err:
 
4306
  session->variables.sql_mode= save_sql_mode;
 
4307
  session->abort_on_warning= 0;
 
4308
  free_io_cache(from);
 
4309
  *copied= found_count;
 
4310
  *deleted=delete_count;
 
4311
  to->file->ha_release_auto_increment();
 
4312
  if (to->file->ha_external_lock(session,F_UNLCK))
 
4313
    error=1;
 
4314
  return(error > 0 ? -1 : 0);
 
4315
}
 
4316
 
 
4317
 
 
4318
/*
 
4319
  Recreates tables by calling mysql_alter_table().
 
4320
 
 
4321
  SYNOPSIS
 
4322
    mysql_recreate_table()
 
4323
    session                     Thread handler
 
4324
    tables              Tables to recreate
 
4325
 
 
4326
 RETURN
 
4327
    Like mysql_alter_table().
 
4328
*/
 
4329
bool mysql_recreate_table(Session *session, TableList *table_list)
 
4330
{
 
4331
  HA_CREATE_INFO create_info;
 
4332
  Alter_info alter_info;
 
4333
 
 
4334
  assert(!table_list->next_global);
 
4335
  /*
 
4336
    table_list->table has been closed and freed. Do not reference
 
4337
    uninitialized data. open_tables() could fail.
 
4338
  */
 
4339
  table_list->table= NULL;
 
4340
 
 
4341
  memset(&create_info, 0, sizeof(create_info));
 
4342
  create_info.row_type=ROW_TYPE_NOT_USED;
 
4343
  create_info.default_table_charset=default_charset_info;
 
4344
  /* Force alter table to recreate table */
 
4345
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
4346
  return(mysql_alter_table(session, NULL, NULL, &create_info,
 
4347
                                table_list, &alter_info, 0,
 
4348
                                (order_st *) 0, 0));
 
4349
}
 
4350
 
 
4351
 
 
4352
bool mysql_checksum_table(Session *session, TableList *tables,
 
4353
                          HA_CHECK_OPT *check_opt)
 
4354
{
 
4355
  TableList *table;
 
4356
  List<Item> field_list;
 
4357
  Item *item;
 
4358
  Protocol *protocol= session->protocol;
 
4359
 
 
4360
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
4361
  item->maybe_null= 1;
 
4362
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
4363
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
4364
  item->maybe_null= 1;
 
4365
  if (protocol->sendFields(&field_list,
 
4366
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
4367
    return(true);
 
4368
 
 
4369
  /* Open one table after the other to keep lock time as short as possible. */
 
4370
  for (table= tables; table; table= table->next_local)
 
4371
  {
 
4372
    char table_name[NAME_LEN*2+2];
 
4373
    Table *t;
 
4374
 
 
4375
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
4376
 
 
4377
    t= table->table= session->open_ltable(table, TL_READ);
 
4378
    session->clear_error();                     // these errors shouldn't get client
 
4379
 
 
4380
    protocol->prepareForResend();
 
4381
    protocol->store(table_name);
 
4382
 
 
4383
    if (!t)
 
4384
    {
 
4385
      /* Table didn't exist */
 
4386
      protocol->store();
 
4387
      session->clear_error();
 
4388
    }
 
4389
    else
 
4390
    {
 
4391
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
4392
          !(check_opt->flags & T_EXTEND))
 
4393
        protocol->store((uint64_t)t->file->checksum());
 
4394
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
4395
               (check_opt->flags & T_QUICK))
 
4396
        protocol->store();
 
4397
      else
 
4398
      {
 
4399
        /* calculating table's checksum */
 
4400
        ha_checksum crc= 0;
 
4401
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
4402
 
 
4403
        t->use_all_columns();
 
4404
 
 
4405
        if (t->file->ha_rnd_init(1))
 
4406
          protocol->store();
 
4407
        else
 
4408
        {
 
4409
          for (;;)
 
4410
          {
 
4411
            ha_checksum row_crc= 0;
 
4412
            int error= t->file->rnd_next(t->record[0]);
 
4413
            if (unlikely(error))
 
4414
            {
 
4415
              if (error == HA_ERR_RECORD_DELETED)
 
4416
                continue;
 
4417
              break;
 
4418
            }
 
4419
            if (t->s->null_bytes)
 
4420
            {
 
4421
              /* fix undefined null bits */
 
4422
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
4423
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
4424
                t->record[0][0] |= 1;
 
4425
 
 
4426
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
4427
            }
 
4428
 
 
4429
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
4430
            {
 
4431
              Field *f= t->field[i];
 
4432
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
4433
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
4434
              {
 
4435
                String tmp;
 
4436
                f->val_str(&tmp);
 
4437
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
4438
              }
 
4439
              else
 
4440
                row_crc= my_checksum(row_crc, f->ptr,
 
4441
                                     f->pack_length());
 
4442
            }
 
4443
 
 
4444
            crc+= row_crc;
 
4445
          }
 
4446
          protocol->store((uint64_t)crc);
 
4447
          t->file->ha_rnd_end();
 
4448
        }
 
4449
      }
 
4450
      session->clear_error();
 
4451
      session->close_thread_tables();
 
4452
      table->table=0;                           // For query cache
 
4453
    }
 
4454
    if (protocol->write())
 
4455
      goto err;
 
4456
  }
 
4457
 
 
4458
  session->my_eof();
 
4459
  return(false);
 
4460
 
 
4461
 err:
 
4462
  session->close_thread_tables();                       // Shouldn't be needed
 
4463
  if (table)
 
4464
    table->table=0;
 
4465
  return(true);
 
4466
}
 
4467
 
 
4468
static bool check_engine(Session *session, const char *table_name,
 
4469
                         HA_CREATE_INFO *create_info)
 
4470
{
 
4471
  StorageEngine **new_engine= &create_info->db_type;
 
4472
  StorageEngine *req_engine= *new_engine;
 
4473
  if (!req_engine->is_enabled())
 
4474
  {
 
4475
    string engine_name= req_engine->getName();
 
4476
    my_error(ER_FEATURE_DISABLED,MYF(0),
 
4477
             engine_name.c_str(), engine_name.c_str());
 
4478
             
 
4479
    return true;
 
4480
  }
 
4481
 
 
4482
  if (req_engine && req_engine != *new_engine)
 
4483
  {
 
4484
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
4485
                       ER_WARN_USING_OTHER_HANDLER,
 
4486
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
4487
                       ha_resolve_storage_engine_name(*new_engine).c_str(),
 
4488
                       table_name);
 
4489
  }
 
4490
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
4491
      (*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
 
4492
  {
 
4493
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
4494
    {
 
4495
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
4496
               ha_resolve_storage_engine_name(*new_engine).c_str(),
 
4497
               "TEMPORARY");
 
4498
      *new_engine= 0;
 
4499
      return true;
 
4500
    }
 
4501
    *new_engine= myisam_engine;
 
4502
  }
 
4503
  if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
4504
     && (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
 
4505
  {
 
4506
    my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
4507
             ha_resolve_storage_engine_name(*new_engine).c_str(),
 
4508
             "non-TEMPORARY");
 
4509
    *new_engine= 0;
 
4510
    return true;
 
4511
  }
 
4512
 
 
4513
  return false;
 
4514
}