~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2009-08-17 01:44:23 UTC
  • mto: This revision was merged to the branch mainline in revision 1118.
  • Revision ID: brian@gaz-20090817014423-jxi2qonsumm8mndf
Remove SQL level reference for DELAY (just now done correctly by default in
engine).

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