~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Stewart Smith
  • Date: 2009-10-19 04:17:38 UTC
  • mto: This revision was merged to the branch mainline in revision 1192.
  • Revision ID: stewart@flamingspork.com-20091019041738-bsjyzmittghcomqj
remove some unused PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP related things as errorcheck mutexes are never used (and haven't been since at least MySQL 4.1

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
36
#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"
 
37
 
 
38
#include "drizzled/statement/alter_table.h" /* for mysql_create_like_schema_frm, which will die soon */
50
39
 
51
40
#include <algorithm>
52
 
#include <sstream>
53
 
 
54
 
#include <boost/unordered_set.hpp>
55
41
 
56
42
using namespace std;
57
 
 
58
 
namespace drizzled
59
 
{
60
 
 
61
 
extern pid_t current_pid;
62
 
 
63
 
bool is_primary_key(KeyInfo *key_info)
 
43
using namespace drizzled;
 
44
 
 
45
static const char hexchars[]= "0123456789abcdef";
 
46
bool is_primary_key(KEY *key_info)
64
47
{
65
48
  static const char * primary_key_name="PRIMARY";
66
49
  return (strcmp(key_info->name, primary_key_name)==0);
75
58
    return NULL;
76
59
}
77
60
 
78
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
79
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
 
61
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
62
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
80
63
 
81
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
82
65
 
83
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
 
66
void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
84
67
{
85
68
  /*
86
69
    If the table character set was not given explicitly,
87
70
    let's fetch the database default character set and
88
71
    apply it to the table.
89
72
  */
90
 
  SchemaIdentifier identifier(db);
91
73
  if (create_info->default_table_charset == NULL)
92
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
74
    create_info->default_table_charset= get_default_db_collation(db);
 
75
}
 
76
 
 
77
/*
 
78
  Translate a file name to a table name (WL #1324).
 
79
 
 
80
  SYNOPSIS
 
81
    filename_to_tablename()
 
82
      from                      The file name
 
83
      to                OUT     The table name
 
84
      to_length                 The size of the table name buffer.
 
85
 
 
86
  RETURN
 
87
    Table name length.
 
88
*/
 
89
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
90
{
 
91
  uint32_t length= 0;
 
92
 
 
93
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
94
  {
 
95
    /* Temporary table name. */
 
96
    length= strlen(strncpy(to, from, to_length));
 
97
  }
 
98
  else
 
99
  {
 
100
    for (; *from  && length < to_length; length++, from++)
 
101
    {
 
102
      if (*from != '@')
 
103
      {
 
104
        to[length]= *from;
 
105
        continue;
 
106
      }
 
107
      /* We've found an escaped char - skip the @ */
 
108
      from++;
 
109
      to[length]= 0;
 
110
      /* There will be a two-position hex-char version of the char */
 
111
      for (int x=1; x >= 0; x--)
 
112
      {
 
113
        if (*from >= '0' && *from <= '9')
 
114
          to[length] += ((*from++ - '0') << (4 * x));
 
115
        else if (*from >= 'a' && *from <= 'f')
 
116
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
117
      }
 
118
      /* Backup because we advanced extra in the inner loop */
 
119
      from--;
 
120
    } 
 
121
  }
 
122
 
 
123
  return length;
 
124
}
 
125
 
 
126
 
 
127
/*
 
128
  Translate a table name to a file name (WL #1324).
 
129
 
 
130
  SYNOPSIS
 
131
    tablename_to_filename()
 
132
      from                      The table name
 
133
      to                OUT     The file name
 
134
      to_length                 The size of the file name buffer.
 
135
 
 
136
  RETURN
 
137
    true if errors happen. false on success.
 
138
*/
 
139
bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
140
{
 
141
  
 
142
  size_t length= 0;
 
143
  for (; *from  && length < to_length; length++, from++)
 
144
  {
 
145
    if ((*from >= '0' && *from <= '9') ||
 
146
        (*from >= 'A' && *from <= 'Z') ||
 
147
        (*from >= 'a' && *from <= 'z') ||
 
148
/* OSX defines an extra set of high-bit and multi-byte characters
 
149
   that cannot be used on the filesystem. Instead of trying to sort
 
150
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
151
   It won't really hurt anything - it'll just make some filenames ugly. */
 
152
#if !defined(TARGET_OS_OSX)
 
153
        ((unsigned char)*from >= 128) ||
 
154
#endif
 
155
        (*from == '_') ||
 
156
        (*from == ' ') ||
 
157
        (*from == '-'))
 
158
    {
 
159
      to[length]= *from;
 
160
      continue;
 
161
    }
 
162
   
 
163
    if (length + 3 >= to_length)
 
164
      return true;
 
165
 
 
166
    /* We need to escape this char in a way that can be reversed */
 
167
    to[length++]= '@';
 
168
    to[length++]= hexchars[(*from >> 4) & 15];
 
169
    to[length]= hexchars[(*from) & 15];
 
170
  }
 
171
 
 
172
  if (check_if_legal_tablename(to) &&
 
173
      length + 4 < to_length)
 
174
  {
 
175
    memcpy(to + length, "@@@", 4);
 
176
    length+= 3;
 
177
  }
 
178
  return false;
 
179
}
 
180
 
 
181
 
 
182
/*
 
183
  Creates path to a file: drizzle_data_dir/db/table.ext
 
184
 
 
185
  SYNOPSIS
 
186
   build_table_filename()
 
187
     buff                       Where to write result
 
188
                                This may be the same as table_name.
 
189
     bufflen                    buff size
 
190
     db                         Database name
 
191
     table_name                 Table name
 
192
     ext                        File extension.
 
193
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
194
                                table_name is temporary, do not change.
 
195
 
 
196
  NOTES
 
197
 
 
198
    Uses database and table name, and extension to create
 
199
    a file name in drizzle_data_dir. Database and table
 
200
    names are converted from system_charset_info into "fscs".
 
201
    Unless flags indicate a temporary table name.
 
202
    'db' is always converted.
 
203
    'ext' is not converted.
 
204
 
 
205
    The conversion suppression is required for ALTER Table. This
 
206
    statement creates intermediate tables. These are regular
 
207
    (non-temporary) tables with a temporary name. Their path names must
 
208
    be derivable from the table name. So we cannot use
 
209
    build_tmptable_filename() for them.
 
210
 
 
211
  RETURN
 
212
    path length on success, 0 on failure
 
213
*/
 
214
 
 
215
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
 
216
{
 
217
  char dbbuff[FN_REFLEN];
 
218
  char tbbuff[FN_REFLEN];
 
219
  bool conversion_error= false;
 
220
 
 
221
  memset(tbbuff, 0, sizeof(tbbuff));
 
222
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
223
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
224
  else
 
225
  {
 
226
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
227
    if (conversion_error)
 
228
    {
 
229
      errmsg_printf(ERRMSG_LVL_ERROR,
 
230
                    _("Table name cannot be encoded and fit within filesystem "
 
231
                      "name length restrictions."));
 
232
      return 0;
 
233
    }
 
234
  }
 
235
  memset(dbbuff, 0, sizeof(dbbuff));
 
236
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
237
  if (conversion_error)
 
238
  {
 
239
    errmsg_printf(ERRMSG_LVL_ERROR,
 
240
                  _("Schema name cannot be encoded and fit within filesystem "
 
241
                    "name length restrictions."));
 
242
    return 0;
 
243
  }
 
244
   
 
245
 
 
246
  int rootdir_len= strlen(FN_ROOTDIR);
 
247
  string table_path(drizzle_data_home);
 
248
  int without_rootdir= table_path.length()-rootdir_len;
 
249
 
 
250
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
251
  if (without_rootdir >= 0)
 
252
  {
 
253
    const char *tmp= table_path.c_str()+without_rootdir;
 
254
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
255
      table_path.append(FN_ROOTDIR);
 
256
  }
 
257
 
 
258
  table_path.append(dbbuff);
 
259
  table_path.append(FN_ROOTDIR);
 
260
  table_path.append(tbbuff);
 
261
 
 
262
  if (bufflen < table_path.length())
 
263
    return 0;
 
264
 
 
265
  strcpy(buff, table_path.c_str());
 
266
 
 
267
  return table_path.length();
 
268
}
 
269
 
 
270
 
 
271
/*
 
272
  Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
 
273
 
 
274
  SYNOPSIS
 
275
   build_tmptable_filename()
 
276
     session                    The thread handle.
 
277
     buff                       Where to write result
 
278
     bufflen                    buff size
 
279
 
 
280
  NOTES
 
281
 
 
282
    Uses current_pid, thread_id, and tmp_table counter to create
 
283
    a file name in drizzle_tmpdir.
 
284
 
 
285
  RETURN
 
286
    path length on success, 0 on failure
 
287
*/
 
288
 
 
289
static uint32_t build_tmptable_filename(Session* session,
 
290
                                        char *buff, size_t bufflen)
 
291
{
 
292
  uint32_t length;
 
293
  ostringstream path_str, post_tmpdir_str;
 
294
  string tmp;
 
295
 
 
296
  path_str << drizzle_tmpdir;
 
297
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
298
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
299
  tmp= post_tmpdir_str.str();
 
300
 
 
301
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
302
 
 
303
  path_str << tmp;
 
304
 
 
305
  if (bufflen < path_str.str().length())
 
306
    length= 0;
 
307
  else
 
308
    length= unpack_filename(buff, path_str.str().c_str());
 
309
 
 
310
  return length;
93
311
}
94
312
 
95
313
/*
104
322
 
105
323
  DESCRIPTION
106
324
    Write the binlog if open, routine used in multiple places in this
107
 
    cursor
108
 
*/
109
 
 
110
 
void write_bin_log(Session *session, const std::string &query)
111
 
{
112
 
  TransactionServices &transaction_services= TransactionServices::singleton();
113
 
  transaction_services.rawStatement(session, query);
 
325
    file
 
326
*/
 
327
 
 
328
void write_bin_log(Session *session,
 
329
                   char const *query, size_t query_length)
 
330
{
 
331
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
332
  replication_services.rawStatement(session, query, query_length);
 
333
}
 
334
 
 
335
 
 
336
/* Should should be refactored to go away */
 
337
static void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
338
{
 
339
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
340
  string built_query;
 
341
 
 
342
  if (if_exists)
 
343
    built_query.append("DROP Table IF EXISTS ");
 
344
  else
 
345
    built_query.append("DROP Table ");
 
346
 
 
347
  built_query.append("`");
 
348
  if (session->db == NULL || strcmp(db_name ,session->db) != 0)
 
349
  {
 
350
    built_query.append(db_name);
 
351
    built_query.append("`.`");
 
352
  }
 
353
 
 
354
  built_query.append(table_name);
 
355
  built_query.append("`");
 
356
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
 
357
}
 
358
 
 
359
 
 
360
/*
 
361
 delete (drop) tables.
 
362
 
 
363
  SYNOPSIS
 
364
   mysql_rm_table()
 
365
   session                      Thread handle
 
366
   tables               List of tables to delete
 
367
   if_exists            If 1, don't give error if one table doesn't exists
 
368
 
 
369
  NOTES
 
370
    Will delete all tables that can be deleted and give a compact error
 
371
    messages for tables that could not be deleted.
 
372
    If a table is in use, we will wait for all users to free the table
 
373
    before dropping it
 
374
 
 
375
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
376
    not if under LOCK TABLES.
 
377
 
 
378
  RETURN
 
379
    false OK.  In this case ok packet is sent to user
 
380
    true  Error
 
381
 
 
382
*/
 
383
 
 
384
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
 
385
{
 
386
  bool error, need_start_waiting= false;
 
387
 
 
388
  if (tables && tables->schema_table)
 
389
  {
 
390
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
391
    return(true);
 
392
  }
 
393
 
 
394
  /* mark for close and remove all cached entries */
 
395
 
 
396
  if (!drop_temporary)
 
397
  {
 
398
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
399
      return(true);
 
400
  }
 
401
 
 
402
  /*
 
403
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
404
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
405
    close their tables. This would make a pretty deadlock.
 
406
  */
 
407
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, false);
 
408
 
 
409
  if (need_start_waiting)
 
410
    start_waiting_global_read_lock(session);
 
411
 
 
412
  if (error)
 
413
    return(true);
 
414
  session->my_ok();
 
415
  return(false);
114
416
}
115
417
 
116
418
/*
118
420
 
119
421
  SYNOPSIS
120
422
    mysql_rm_table_part2()
121
 
    session                     Thread Cursor
 
423
    session                     Thread handler
122
424
    tables              Tables to drop
123
425
    if_exists           If set, don't give an error if table doesn't exists.
124
426
                        In this case we give an warning of level 'NOTE'
125
427
    drop_temporary      Only drop temporary tables
 
428
    dont_log_query      Don't write query to log files. This will also not
 
429
                        generate warnings if the handler files doesn't exists
126
430
 
127
 
  @todo
 
431
  TODO:
128
432
    When logging to the binary log, we should log
129
433
    tmp_tables and transactional tables as separate statements if we
130
434
    are in a transaction;  This is needed to get these tables into the
141
445
*/
142
446
 
143
447
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
144
 
                         bool drop_temporary)
 
448
                         bool drop_temporary, bool dont_log_query)
145
449
{
146
450
  TableList *table;
 
451
  char path[FN_REFLEN];
 
452
  uint32_t path_length= 0;
147
453
  String wrong_tables;
148
454
  int error= 0;
149
455
  bool foreign_key_error= false;
150
456
 
151
 
  {
152
 
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
153
 
 
154
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
 
    {
156
 
      table::Cache::singleton().mutex().unlock();
157
 
      return 1;
158
 
    }
159
 
 
160
 
    /* Don't give warnings for not found errors, as we already generate notes */
161
 
    session->no_warnings_for_error= 1;
162
 
 
163
 
    for (table= tables; table; table= table->next_local)
164
 
    {
165
 
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
166
 
 
167
 
      error= session->drop_temporary_table(tmp_identifier);
168
 
 
169
 
      switch (error) {
170
 
      case  0:
171
 
        // removed temporary table
172
 
        continue;
173
 
      case -1:
 
457
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
458
 
 
459
  /*
 
460
    If we have the table in the definition cache, we don't have to check the
 
461
    .frm file to find if the table is a normal table (not view) and what
 
462
    engine to use.
 
463
  */
 
464
 
 
465
  for (table= tables; table; table= table->next_local)
 
466
  {
 
467
    TableShare *share;
 
468
    table->db_type= NULL;
 
469
    if ((share= TableShare::getShare(table->db, table->table_name)))
 
470
      table->db_type= share->db_type();
 
471
  }
 
472
 
 
473
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
474
  {
 
475
    pthread_mutex_unlock(&LOCK_open);
 
476
    return 1;
 
477
  }
 
478
 
 
479
  /* Don't give warnings for not found errors, as we already generate notes */
 
480
  session->no_warnings_for_error= 1;
 
481
 
 
482
  for (table= tables; table; table= table->next_local)
 
483
  {
 
484
    char *db=table->db;
 
485
    plugin::StorageEngine *table_type;
 
486
 
 
487
    error= session->drop_temporary_table(table);
 
488
 
 
489
    switch (error) {
 
490
    case  0:
 
491
      // removed temporary table
 
492
      continue;
 
493
    case -1:
 
494
      error= 1;
 
495
      goto err_with_placeholders;
 
496
    default:
 
497
      // temporary table not found
 
498
      error= 0;
 
499
    }
 
500
 
 
501
    table_type= table->db_type;
 
502
    if (!drop_temporary)
 
503
    {
 
504
      Table *locked_table;
 
505
      abort_locked_tables(session, db, table->table_name);
 
506
      remove_table_from_cache(session, db, table->table_name,
 
507
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
508
                              RTFC_CHECK_KILLED_FLAG);
 
509
      /*
 
510
        If the table was used in lock tables, remember it so that
 
511
        unlock_table_names can free it
 
512
      */
 
513
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
514
        table->table= locked_table;
 
515
 
 
516
      if (session->killed)
 
517
      {
 
518
        error= -1;
 
519
        goto err_with_placeholders;
 
520
      }
 
521
      /* remove .frm file and engine files */
 
522
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
 
523
    }
 
524
 
 
525
    if (drop_temporary ||
 
526
        ((table_type == NULL
 
527
          && (plugin::StorageEngine::getTableProto(path, NULL) != EEXIST))))
 
528
    {
 
529
      // Table was not found on disk and table can't be created from engine
 
530
      if (if_exists)
 
531
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
532
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
533
                            table->table_name);
 
534
      else
174
535
        error= 1;
175
 
        goto err_with_placeholders;
176
 
      default:
177
 
        // temporary table not found
178
 
        error= 0;
179
 
      }
180
 
 
181
 
      if (drop_temporary == false)
182
 
      {
183
 
        Table *locked_table;
184
 
        abort_locked_tables(session, tmp_identifier);
185
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
186
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
187
 
                                              RTFC_CHECK_KILLED_FLAG);
188
 
        /*
189
 
          If the table was used in lock tables, remember it so that
190
 
          unlock_table_names can free it
191
 
        */
192
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
193
 
          table->table= locked_table;
194
 
 
195
 
        if (session->getKilled())
196
 
        {
197
 
          error= -1;
198
 
          goto err_with_placeholders;
199
 
        }
200
 
      }
201
 
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
202
 
 
203
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
 
      {
205
 
        // Table was not found on disk and table can't be created from engine
206
 
        if (if_exists)
207
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
208
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
209
 
                              table->getTableName());
210
 
        else
211
 
          error= 1;
212
 
      }
213
 
      else
214
 
      {
215
 
        error= plugin::StorageEngine::dropTable(*session, identifier);
216
 
 
217
 
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
218
 
        {
219
 
          error= 0;
220
 
          session->clear_error();
221
 
        }
222
 
 
223
 
        if (error == HA_ERR_ROW_IS_REFERENCED)
224
 
        {
225
 
          /* the table is referenced by a foreign key constraint */
226
 
          foreign_key_error= true;
227
 
        }
228
 
      }
229
 
 
230
 
      if (error == 0 || (if_exists && foreign_key_error == false))
231
 
      {
232
 
        TransactionServices &transaction_services= TransactionServices::singleton();
233
 
        transaction_services.dropTable(session, string(table->getSchemaName()), string(table->getTableName()), if_exists);
234
 
      }
235
 
 
236
 
      if (error)
237
 
      {
238
 
        if (wrong_tables.length())
239
 
          wrong_tables.append(',');
240
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
241
 
      }
242
 
    }
243
 
    /*
244
 
      It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
245
 
      on the table name.
246
 
    */
247
 
    table::Cache::singleton().mutex().unlock();
 
536
    }
 
537
    else
 
538
    {
 
539
      error= plugin::StorageEngine::deleteTable(session, path, db,
 
540
                                                table->table_name,
 
541
                                                ! dont_log_query);
 
542
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
543
      {
 
544
        error= 0;
 
545
        session->clear_error();
 
546
      }
 
547
 
 
548
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
549
      {
 
550
        /* the table is referenced by a foreign key constraint */
 
551
        foreign_key_error= true;
 
552
      }
 
553
    }
 
554
 
 
555
    if (error == 0 || (if_exists && foreign_key_error == false))
 
556
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
557
 
 
558
    if (error)
 
559
    {
 
560
      if (wrong_tables.length())
 
561
        wrong_tables.append(',');
 
562
      wrong_tables.append(String(table->table_name,system_charset_info));
 
563
    }
248
564
  }
 
565
  /*
 
566
    It's safe to unlock LOCK_open: we have an exclusive lock
 
567
    on the table name.
 
568
  */
 
569
  pthread_mutex_unlock(&LOCK_open);
249
570
  error= 0;
250
 
 
251
571
  if (wrong_tables.length())
252
572
  {
253
 
    if (not foreign_key_error)
254
 
    {
 
573
    if (!foreign_key_error)
255
574
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
575
                      wrong_tables.c_ptr());
257
 
    }
258
576
    else
259
577
    {
260
578
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
262
580
    error= 1;
263
581
  }
264
582
 
265
 
  table::Cache::singleton().mutex().lock(); /* final bit in rm table lock */
266
 
 
 
583
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
267
584
err_with_placeholders:
268
 
  tables->unlock_table_names();
269
 
  table::Cache::singleton().mutex().unlock();
 
585
  unlock_table_names(tables, NULL);
 
586
  pthread_mutex_unlock(&LOCK_open);
270
587
  session->no_warnings_for_error= 0;
271
588
 
272
 
  return error;
 
589
  return(error);
 
590
}
 
591
 
 
592
 
 
593
/*
 
594
  Quickly remove a table.
 
595
 
 
596
  SYNOPSIS
 
597
    quick_rm_table()
 
598
      base                      The plugin::StorageEngine handle.
 
599
      db                        The database name.
 
600
      table_name                The table name.
 
601
      is_tmp                    If the table is temp.
 
602
 
 
603
  RETURN
 
604
    0           OK
 
605
    != 0        Error
 
606
*/
 
607
 
 
608
bool quick_rm_table(plugin::StorageEngine *, const char *db,
 
609
                    const char *table_name, bool is_tmp)
 
610
{
 
611
  char path[FN_REFLEN];
 
612
  bool error= 0;
 
613
 
 
614
  build_table_filename(path, sizeof(path), db, table_name, is_tmp);
 
615
 
 
616
  return (plugin::StorageEngine::deleteTable(current_session, path, db,
 
617
                                             table_name, 0)
 
618
          || error);
273
619
}
274
620
 
275
621
/*
285
631
  PRIMARY keys are prioritized.
286
632
*/
287
633
 
288
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
634
static int sort_keys(KEY *a, KEY *b)
289
635
{
290
636
  ulong a_flags= a->flags, b_flags= b->flags;
291
637
 
337
683
    1             Error
338
684
*/
339
685
 
340
 
class typelib_set_member
341
 
{
342
 
public:
343
 
  string s;
344
 
  const CHARSET_INFO * const cs;
345
 
 
346
 
  typelib_set_member(const char* value, unsigned int length,
347
 
                     const CHARSET_INFO * const charset)
348
 
    : s(value, length),
349
 
      cs(charset)
350
 
  {}
351
 
};
352
 
 
353
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
354
 
{
355
 
  return (my_strnncoll(a.cs,
356
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
357
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
358
 
}
359
 
 
360
 
 
361
 
namespace
362
 
{
363
 
class typelib_set_member_hasher
364
 
{
365
 
  boost::hash<string> hasher;
366
 
public:
367
 
  std::size_t operator()(const typelib_set_member& t) const
368
 
  {
369
 
    return hasher(t.s);
370
 
  }
371
 
};
372
 
}
373
 
 
374
686
static bool check_duplicates_in_interval(const char *set_or_name,
375
687
                                         const char *name, TYPELIB *typelib,
376
688
                                         const CHARSET_INFO * const cs,
381
693
  unsigned int *cur_length= typelib->type_lengths;
382
694
  *dup_val_count= 0;
383
695
 
384
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
385
 
 
386
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
696
  for ( ; tmp.count > 1; cur_value++, cur_length++)
387
697
  {
388
698
    tmp.type_names++;
389
699
    tmp.type_lengths++;
390
700
    tmp.count--;
391
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
701
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
392
702
    {
393
703
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
394
704
               name,*cur_value,set_or_name);
395
705
      return 1;
396
706
    }
397
 
    else
398
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
399
707
  }
400
708
  return 0;
401
709
}
444
752
    sql_field     field to prepare for packing
445
753
    blob_columns  count for BLOBs
446
754
    timestamps    count for timestamps
 
755
    table_flags   table flags
447
756
 
448
757
  DESCRIPTION
449
758
    This function prepares a CreateField instance.
455
764
*/
456
765
int prepare_create_field(CreateField *sql_field,
457
766
                         uint32_t *blob_columns,
458
 
                         int *timestamps,
459
 
                         int *timestamps_with_niladic)
 
767
                         int *timestamps, int *timestamps_with_niladic,
 
768
                         int64_t )
460
769
{
461
770
  unsigned int dup_val_count;
462
771
 
468
777
 
469
778
  switch (sql_field->sql_type) {
470
779
  case DRIZZLE_TYPE_BLOB:
 
780
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
471
781
    sql_field->length= 8; // Unireg field length
472
782
    (*blob_columns)++;
473
783
    break;
474
784
  case DRIZZLE_TYPE_VARCHAR:
 
785
    sql_field->pack_flag=0;
475
786
    break;
476
787
  case DRIZZLE_TYPE_ENUM:
 
788
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
477
789
    if (check_duplicates_in_interval("ENUM",
478
790
                                     sql_field->field_name,
479
791
                                     sql_field->interval,
484
796
  case DRIZZLE_TYPE_DATE:  // Rest of string types
485
797
  case DRIZZLE_TYPE_DATETIME:
486
798
  case DRIZZLE_TYPE_NULL:
 
799
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
487
800
    break;
488
 
  case DRIZZLE_TYPE_DECIMAL:
 
801
  case DRIZZLE_TYPE_NEWDECIMAL:
 
802
    sql_field->pack_flag= 0;
489
803
    break;
490
804
  case DRIZZLE_TYPE_TIMESTAMP:
491
805
    /* We should replace old TIMESTAMP fields with their newer analogs */
497
811
        (*timestamps_with_niladic)++;
498
812
      }
499
813
      else
500
 
      {
501
814
        sql_field->unireg_check= Field::NONE;
502
 
      }
503
815
    }
504
816
    else if (sql_field->unireg_check != Field::NONE)
505
817
      (*timestamps_with_niladic)++;
507
819
    (*timestamps)++;
508
820
    /* fall-through */
509
821
  default:
 
822
    sql_field->pack_flag=(0 |
 
823
                          f_settype((uint32_t) sql_field->sql_type));
510
824
    break;
511
825
  }
512
 
 
513
826
  return 0;
514
827
}
515
828
 
516
 
static int mysql_prepare_create_table(Session *session,
517
 
                                      HA_CREATE_INFO *create_info,
518
 
                                      message::Table &create_proto,
519
 
                                      AlterInfo *alter_info,
520
 
                                      bool tmp_table,
521
 
                                      uint32_t *db_options,
522
 
                                      KeyInfo **key_info_buffer,
523
 
                                      uint32_t *key_count,
524
 
                                      int select_field_count)
 
829
int mysql_prepare_create_table(Session *session,
 
830
                               HA_CREATE_INFO *create_info,
 
831
                               AlterInfo *alter_info,
 
832
                               bool tmp_table,
 
833
                               uint32_t *db_options,
 
834
                               handler *file,
 
835
                               KEY **key_info_buffer,
 
836
                               uint32_t *key_count,
 
837
                               int select_field_count)
525
838
{
526
839
  const char    *key_name;
527
840
  CreateField   *sql_field,*dup_field;
528
841
  uint          field,null_fields,blob_columns,max_key_length;
529
842
  ulong         record_offset= 0;
530
 
  KeyInfo               *key_info;
531
 
  KeyPartInfo *key_part_info;
 
843
  KEY           *key_info;
 
844
  KEY_PART_INFO *key_part_info;
532
845
  int           timestamps= 0, timestamps_with_niladic= 0;
533
846
  int           field_no,dup_no;
534
847
  int           select_field_pos,auto_increment=0;
536
849
  List_iterator<CreateField> it2(alter_info->create_list);
537
850
  uint32_t total_uneven_bit_length= 0;
538
851
 
539
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
540
 
 
541
852
  select_field_pos= alter_info->create_list.elements - select_field_count;
542
853
  null_fields=blob_columns=0;
543
 
  max_key_length= engine->max_key_length();
 
854
  max_key_length= file->max_key_length();
544
855
 
545
856
  for (field_no=0; (sql_field=it++) ; field_no++)
546
857
  {
606
917
 
607
918
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
608
919
    {
609
 
      size_t dummy;
 
920
      uint32_t dummy;
610
921
      const CHARSET_INFO * const cs= sql_field->charset;
611
922
      TYPELIB *interval= sql_field->interval;
612
923
 
639
950
          if (String::needs_conversion(tmp->length(), tmp->charset(),
640
951
                                       cs, &dummy))
641
952
          {
642
 
            size_t cnv_errs;
 
953
            uint32_t cnv_errs;
643
954
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
644
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
955
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
956
                                                  conv.length());
645
957
            interval->type_lengths[i]= conv.length();
646
958
          }
647
959
 
681
993
            }
682
994
          }
683
995
        }
684
 
        uint32_t new_dummy;
685
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
996
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
686
997
        sql_field->length= field_length;
687
998
      }
688
999
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
746
1057
        }
747
1058
      }
748
1059
    }
749
 
 
750
 
    /** @todo Get rid of this MyISAM-specific crap. */
751
 
    if (not create_proto.engine().name().compare("MyISAM") &&
752
 
        ((sql_field->flags & BLOB_FLAG) ||
753
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
 
1060
    /* Don't pack rows in old tables if the user has requested this */
 
1061
    if ((sql_field->flags & BLOB_FLAG) ||
 
1062
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
754
1063
      (*db_options)|= HA_OPTION_PACK_RECORD;
755
1064
    it2.rewind();
756
1065
  }
765
1074
    assert(sql_field->charset != 0);
766
1075
 
767
1076
    if (prepare_create_field(sql_field, &blob_columns,
768
 
                             &timestamps, &timestamps_with_niladic))
 
1077
                             &timestamps, &timestamps_with_niladic,
 
1078
                             file->ha_table_flags()))
769
1079
      return(true);
770
1080
    sql_field->offset= record_offset;
771
1081
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
783
1093
    return(true);
784
1094
  }
785
1095
  if (auto_increment &&
786
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1096
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
787
1097
  {
788
1098
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
789
1099
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
790
1100
    return(true);
791
1101
  }
792
1102
 
793
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1103
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
794
1104
  {
795
1105
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
796
1106
               MYF(0));
818
1128
      fk_key_count++;
819
1129
      if (((Foreign_key *)key)->validate(alter_info->create_list))
820
1130
        return true;
821
 
 
822
1131
      Foreign_key *fk_key= (Foreign_key*) key;
823
 
 
824
 
      add_foreign_key_to_table_message(&create_proto,
825
 
                                       fk_key->name.str,
826
 
                                       fk_key->columns,
827
 
                                       fk_key->ref_table,
828
 
                                       fk_key->ref_columns,
829
 
                                       fk_key->delete_opt,
830
 
                                       fk_key->update_opt,
831
 
                                       fk_key->match_opt);
832
 
 
833
1132
      if (fk_key->ref_columns.elements &&
834
1133
          fk_key->ref_columns.elements != fk_key->columns.elements)
835
1134
      {
842
1141
      continue;
843
1142
    }
844
1143
    (*key_count)++;
845
 
    tmp= engine->max_key_parts();
 
1144
    tmp=file->max_key_parts();
846
1145
    if (key->columns.elements > tmp)
847
1146
    {
848
1147
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
864
1163
             key2->name.str != ignore_key &&
865
1164
             !foreign_key_prefix(key, key2)))
866
1165
        {
867
 
          /* @todo issue warning message */
 
1166
          /* TODO: issue warning message */
868
1167
          /* mark that the generated key should be ignored */
869
1168
          if (!key2->generated ||
870
1169
              (key->generated && key->columns.elements <
891
1190
      return(true);
892
1191
    }
893
1192
  }
894
 
  tmp= engine->max_keys();
 
1193
  tmp=file->max_keys();
895
1194
  if (*key_count > tmp)
896
1195
  {
897
1196
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
898
1197
    return(true);
899
1198
  }
900
1199
 
901
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
902
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
1200
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1201
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
903
1202
  if (!*key_info_buffer || ! key_part_info)
904
1203
    return(true);                               // Out of memory
905
1204
 
939
1238
    key_info->usable_key_parts= key_number;
940
1239
    key_info->algorithm= key->key_create_info.algorithm;
941
1240
 
 
1241
    /* Take block size from key part or table part */
 
1242
    /*
 
1243
      TODO: Add warning if block size changes. We can't do it here, as
 
1244
      this may depend on the size of the key
 
1245
    */
 
1246
    key_info->block_size= (key->key_create_info.block_size ?
 
1247
                           key->key_create_info.block_size :
 
1248
                           create_info->key_block_size);
 
1249
 
 
1250
    if (key_info->block_size)
 
1251
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
1252
 
942
1253
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
943
1254
                                           key->key_create_info.comment.str,
944
1255
                                           key->key_create_info.comment.str +
960
1271
      key_info->comment.str= key->key_create_info.comment.str;
961
1272
    }
962
1273
 
963
 
    message::Table::Field *protofield= NULL;
964
 
 
965
1274
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
966
1275
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
967
1276
    {
968
1277
      uint32_t length;
969
1278
      Key_part_spec *dup_column;
970
 
      int proto_field_nr= 0;
971
1279
 
972
1280
      it.rewind();
973
1281
      field=0;
974
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
1282
      while ((sql_field=it++) &&
975
1283
             my_strcasecmp(system_charset_info,
976
1284
                           column->field_name.str,
977
1285
                           sql_field->field_name))
984
1292
      while ((dup_column= cols2++) != column)
985
1293
      {
986
1294
        if (!my_strcasecmp(system_charset_info,
987
 
                           column->field_name.str, dup_column->field_name.str))
 
1295
                           column->field_name.str, dup_column->field_name.str))
988
1296
        {
989
1297
          my_printf_error(ER_DUP_FIELDNAME,
990
1298
                          ER(ER_DUP_FIELDNAME),MYF(0),
993
1301
        }
994
1302
      }
995
1303
      cols2.rewind();
996
 
 
997
 
      if (create_proto.field_size() > 0)
998
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
999
 
 
1000
1304
      {
1001
1305
        column->length*= sql_field->charset->mbmaxlen;
1002
1306
 
1003
1307
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1004
1308
        {
1005
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
 
1309
          if (! (file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1006
1310
          {
1007
1311
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1008
1312
            return true;
1020
1324
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1021
1325
            sql_field->flags|= NOT_NULL_FLAG;
1022
1326
            null_fields--;
1023
 
 
1024
 
            if (protofield)
1025
 
            {
1026
 
              message::Table::Field::FieldConstraints *constraints;
1027
 
              constraints= protofield->mutable_constraints();
1028
 
              constraints->set_is_nullable(false);
1029
 
            }
1030
 
 
1031
1327
          }
1032
1328
          else
1033
1329
          {
1034
1330
            key_info->flags|= HA_NULL_PART_KEY;
1035
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1331
            if (! (file->ha_table_flags() & HA_NULL_IN_KEY))
1036
1332
            {
1037
1333
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1038
1334
              return true;
1041
1337
        }
1042
1338
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1043
1339
        {
1044
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
 
1340
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
1045
1341
            auto_increment--;                   // Field is used
1046
1342
        }
1047
1343
      }
1048
1344
 
1049
1345
      key_part_info->fieldnr= field;
1050
1346
      key_part_info->offset=  (uint16_t) sql_field->offset;
1051
 
      key_part_info->key_type= 0;
 
1347
      key_part_info->key_type=sql_field->pack_flag;
1052
1348
      length= sql_field->key_length;
1053
1349
 
1054
1350
      if (column->length)
1056
1352
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1057
1353
        {
1058
1354
          if ((length=column->length) > max_key_length ||
1059
 
              length > engine->max_key_part_length())
 
1355
              length > file->max_key_part_length())
1060
1356
          {
1061
 
            length= min(max_key_length, engine->max_key_part_length());
 
1357
            length= min(max_key_length, file->max_key_part_length());
1062
1358
            if (key->type == Key::MULTIPLE)
1063
1359
            {
1064
1360
              /* not a critical problem */
1083
1379
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1084
1380
          return(true);
1085
1381
        }
1086
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1087
 
        {
 
1382
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1088
1383
          length=column->length;
1089
 
        }
1090
1384
      }
1091
1385
      else if (length == 0)
1092
1386
      {
1093
1387
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1094
1388
          return(true);
1095
1389
      }
1096
 
      if (length > engine->max_key_part_length())
 
1390
      if (length > file->max_key_part_length())
1097
1391
      {
1098
 
        length= engine->max_key_part_length();
 
1392
        length= file->max_key_part_length();
1099
1393
        if (key->type == Key::MULTIPLE)
1100
1394
        {
1101
1395
          /* not a critical problem */
1116
1410
      key_part_info->length=(uint16_t) length;
1117
1411
      /* Use packed keys for long strings on the first column */
1118
1412
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1119
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1120
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1121
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1413
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1414
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1415
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1122
1416
      {
1123
1417
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1124
1418
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1125
 
        {
1126
1419
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1127
 
        }
1128
1420
        else
1129
 
        {
1130
1421
          key_info->flags|= HA_PACK_KEY;
1131
 
        }
1132
1422
      }
1133
1423
      /* Check if the key segment is partial, set the key flag accordingly */
1134
1424
      if (length != sql_field->key_length)
1179
1469
    key_info++;
1180
1470
  }
1181
1471
  if (!unique_key && !primary_key &&
1182
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1472
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1183
1473
  {
1184
1474
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1185
1475
    return(true);
1190
1480
    return(true);
1191
1481
  }
1192
1482
  /* Sort keys in optimized order */
1193
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1194
 
                     (qsort_cmp) sort_keys);
 
1483
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1484
           (qsort_cmp) sort_keys);
1195
1485
 
1196
1486
  /* Check fields. */
1197
1487
  it.rewind();
1264
1554
  return 0;
1265
1555
}
1266
1556
 
1267
 
static bool locked_create_event(Session *session,
1268
 
                                const TableIdentifier &identifier,
1269
 
                                HA_CREATE_INFO *create_info,
1270
 
                                message::Table &table_proto,
1271
 
                                AlterInfo *alter_info,
1272
 
                                bool is_if_not_exists,
1273
 
                                bool internal_tmp_table,
1274
 
                                uint db_options,
1275
 
                                uint key_count,
1276
 
                                KeyInfo *key_info_buffer)
1277
 
{
1278
 
  bool error= true;
1279
 
 
1280
 
  {
1281
 
 
1282
 
    /*
1283
 
      @note if we are building a temp table we need to check to see if a temp table
1284
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1285
 
      to create a table under a temporary table.
1286
 
    */
1287
 
    bool exists= 
1288
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1289
 
                                            identifier.getType() != message::Table::STANDARD );
1290
 
 
1291
 
    if (exists)
1292
 
    {
1293
 
      if (is_if_not_exists)
1294
 
      {
1295
 
        error= false;
1296
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1297
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1298
 
                            identifier.getTableName().c_str());
1299
 
        create_info->table_existed= 1;          // Mark that table existed
1300
 
        return error;
1301
 
      }
1302
 
 
1303
 
      std::string path;
1304
 
      identifier.getSQLPath(path);
1305
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1306
 
 
1307
 
      return error;
1308
 
    }
1309
 
 
1310
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1311
 
    {
1312
 
      /*
1313
 
        We don't assert here, but check the result, because the table could be
1314
 
        in the table definition cache and in the same time the .frm could be
1315
 
        missing from the disk, in case of manual intervention which deletes
1316
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1317
 
        Then she could create the table. This case is pretty obscure and
1318
 
        therefore we don't introduce a new error message only for it.
1319
 
      */
1320
 
      /*
1321
 
        @todo improve this error condition.
1322
 
      */
1323
 
      if (definition::Cache::singleton().find(identifier.getKey()))
1324
 
      {
1325
 
        std::string path;
1326
 
        identifier.getSQLPath(path);
1327
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1328
 
 
1329
 
        return error;
1330
 
      }
1331
 
    }
1332
 
  }
1333
 
 
1334
 
  session->set_proc_info("creating table");
1335
 
  create_info->table_existed= 0;                // Mark that table is created
1336
 
 
1337
 
  create_info->table_options= db_options;
1338
 
 
1339
 
  if (not rea_create_table(session, identifier,
1340
 
                           table_proto,
1341
 
                           create_info, alter_info->create_list,
1342
 
                           key_count, key_info_buffer))
1343
 
  {
1344
 
    return error;
1345
 
  }
1346
 
 
1347
 
  if (identifier.getType() == message::Table::TEMPORARY)
1348
 
  {
1349
 
    /* Open table and put in temporary table list */
1350
 
    if (not (session->open_temporary_table(identifier)))
1351
 
    {
1352
 
      (void) session->rm_temporary_table(identifier);
1353
 
      return error;
1354
 
    }
1355
 
  }
1356
 
 
1357
 
  /* 
1358
 
    We keep this behind the lock to make sure ordering is correct for a table.
1359
 
    This is a very unlikely problem where before we would write out to the
1360
 
    trans log, someone would do a delete/create operation.
1361
 
  */
1362
 
 
1363
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1364
 
  {
1365
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1366
 
    transaction_services.createTable(session, table_proto);
1367
 
  }
1368
 
 
1369
 
  return false;
1370
 
}
1371
 
 
1372
1557
 
1373
1558
/*
1374
1559
  Ignore the name of this function... it locks :(
1401
1586
*/
1402
1587
 
1403
1588
bool mysql_create_table_no_lock(Session *session,
1404
 
                                const TableIdentifier &identifier,
 
1589
                                const char *db, const char *table_name,
1405
1590
                                HA_CREATE_INFO *create_info,
1406
 
                                message::Table &table_proto,
 
1591
                                message::Table *table_proto,
1407
1592
                                AlterInfo *alter_info,
1408
1593
                                bool internal_tmp_table,
1409
 
                                uint32_t select_field_count,
1410
 
                                bool is_if_not_exists)
 
1594
                                uint32_t select_field_count)
1411
1595
{
 
1596
  char          path[FN_REFLEN];
 
1597
  uint32_t          path_length;
1412
1598
  uint          db_options, key_count;
1413
 
  KeyInfo               *key_info_buffer;
 
1599
  KEY           *key_info_buffer;
 
1600
  handler       *file;
1414
1601
  bool          error= true;
1415
 
 
1416
1602
  /* Check for duplicate fields and check type of table to create */
1417
 
  if (not alter_info->create_list.elements)
 
1603
  if (!alter_info->create_list.elements)
1418
1604
  {
1419
1605
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1420
1606
               MYF(0));
1421
1607
    return true;
1422
1608
  }
1423
 
  assert(identifier.getTableName() == table_proto.name());
 
1609
  assert(strcmp(table_name,table_proto->name().c_str())==0);
 
1610
  if (check_engine(session, table_name, create_info))
 
1611
    return true;
1424
1612
  db_options= create_info->table_options;
1425
 
 
1426
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1427
 
 
1428
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1429
 
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1430
 
                                     internal_tmp_table,
1431
 
                                     &db_options,
1432
 
                                     &key_info_buffer, &key_count,
1433
 
                                     select_field_count))
1434
 
  {
1435
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1436
 
    error= locked_create_event(session,
1437
 
                               identifier,
1438
 
                               create_info,
1439
 
                               table_proto,
1440
 
                               alter_info,
1441
 
                               is_if_not_exists,
1442
 
                               internal_tmp_table,
1443
 
                               db_options, key_count,
1444
 
                               key_info_buffer);
1445
 
  }
1446
 
 
1447
 
  session->set_proc_info("After create");
1448
 
 
1449
 
  return(error);
1450
 
}
1451
 
 
1452
 
/**
1453
 
  @note the following two methods implement create [temporary] table.
1454
 
*/
1455
 
static bool drizzle_create_table(Session *session,
1456
 
                                 const TableIdentifier &identifier,
1457
 
                                 HA_CREATE_INFO *create_info,
1458
 
                                 message::Table &table_proto,
1459
 
                                 AlterInfo *alter_info,
1460
 
                                 bool internal_tmp_table,
1461
 
                                 uint32_t select_field_count,
1462
 
                                 bool is_if_not_exists)
1463
 
{
1464
 
  Table *name_lock= NULL;
1465
 
  bool result;
1466
 
 
1467
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1468
 
  {
1469
 
    result= true;
1470
 
  }
1471
 
  else if (name_lock == NULL)
1472
 
  {
1473
 
    if (is_if_not_exists)
1474
 
    {
 
1613
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1614
    db_options|=HA_OPTION_PACK_RECORD;
 
1615
  if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
 
1616
                              create_info->db_type)))
 
1617
  {
 
1618
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
1619
    return true;
 
1620
  }
 
1621
 
 
1622
  set_table_default_charset(create_info, (char*) db);
 
1623
 
 
1624
  if (mysql_prepare_create_table(session, create_info, alter_info,
 
1625
                                 internal_tmp_table,
 
1626
                                 &db_options, file,
 
1627
                                 &key_info_buffer, &key_count,
 
1628
                                 select_field_count))
 
1629
    goto err;
 
1630
 
 
1631
      /* Check if table exists */
 
1632
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1633
  {
 
1634
    path_length= build_tmptable_filename(session, path, sizeof(path));
 
1635
  }
 
1636
  else
 
1637
  {
 
1638
 #ifdef FN_DEVCHAR
 
1639
    /* check if the table name contains FN_DEVCHAR when defined */
 
1640
    if (strchr(table_name, FN_DEVCHAR))
 
1641
    {
 
1642
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
 
1643
      return true;
 
1644
    }
 
1645
#endif
 
1646
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
 
1647
  }
 
1648
 
 
1649
  /* Check if table already exists */
 
1650
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1651
      session->find_temporary_table(db, table_name))
 
1652
  {
 
1653
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1654
    {
 
1655
      create_info->table_existed= 1;            // Mark that table existed
1475
1656
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1476
1657
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1477
 
                          identifier.getTableName().c_str());
1478
 
      create_info->table_existed= 1;
1479
 
      result= false;
1480
 
    }
1481
 
    else
1482
 
    {
1483
 
      std::string path;
1484
 
      identifier.getSQLPath(path);
1485
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1486
 
      result= true;
1487
 
    }
1488
 
  }
1489
 
  else
1490
 
  {
1491
 
    result= mysql_create_table_no_lock(session,
1492
 
                                       identifier,
1493
 
                                       create_info,
1494
 
                                       table_proto,
1495
 
                                       alter_info,
1496
 
                                       internal_tmp_table,
1497
 
                                       select_field_count,
1498
 
                                       is_if_not_exists);
1499
 
  }
1500
 
 
1501
 
  if (name_lock)
1502
 
  {
1503
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1504
 
    session->unlink_open_table(name_lock);
1505
 
  }
1506
 
 
1507
 
  return(result);
 
1658
                          table_name);
 
1659
      error= 0;
 
1660
      goto err;
 
1661
    }
 
1662
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1663
    goto err;
 
1664
  }
 
1665
 
 
1666
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1667
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1668
  {
 
1669
    if (plugin::StorageEngine::getTableProto(path, NULL)==EEXIST)
 
1670
    {
 
1671
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1672
      {
 
1673
        error= false;
 
1674
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1675
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1676
                            table_name);
 
1677
        create_info->table_existed= 1;          // Mark that table existed
 
1678
      }
 
1679
      else 
 
1680
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1681
 
 
1682
      goto unlock_and_end;
 
1683
    }
 
1684
    /*
 
1685
      We don't assert here, but check the result, because the table could be
 
1686
      in the table definition cache and in the same time the .frm could be
 
1687
      missing from the disk, in case of manual intervention which deletes
 
1688
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1689
      Then she could create the table. This case is pretty obscure and
 
1690
      therefore we don't introduce a new error message only for it.
 
1691
    */
 
1692
    if (TableShare::getShare(db, table_name))
 
1693
    {
 
1694
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1695
      goto unlock_and_end;
 
1696
    }
 
1697
  }
 
1698
 
 
1699
  /*
 
1700
    Check that table with given name does not already
 
1701
    exist in any storage engine. In such a case it should
 
1702
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1703
    unless user specified CREATE TABLE IF EXISTS
 
1704
    The LOCK_open mutex has been locked to make sure no
 
1705
    one else is attempting to discover the table. Since
 
1706
    it's not on disk as a frm file, no one could be using it!
 
1707
  */
 
1708
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1709
  {
 
1710
    bool create_if_not_exists =
 
1711
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1712
 
 
1713
    char table_path[FN_REFLEN];
 
1714
    uint32_t          table_path_length;
 
1715
 
 
1716
    table_path_length= build_table_filename(table_path, sizeof(table_path),
 
1717
                                            db, table_name, false);
 
1718
 
 
1719
    int retcode= plugin::StorageEngine::getTableProto(table_path, NULL);
 
1720
    switch (retcode)
 
1721
    {
 
1722
      case ENOENT:
 
1723
        /* Normal case, no table exists. we can go and create it */
 
1724
        break;
 
1725
      case EEXIST:
 
1726
        if (create_if_not_exists)
 
1727
        {
 
1728
          error= false;
 
1729
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1730
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1731
                              table_name);
 
1732
          create_info->table_existed= 1;                // Mark that table existed
 
1733
          goto unlock_and_end;
 
1734
        }
 
1735
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1736
        goto unlock_and_end;
 
1737
      default:
 
1738
        my_error(retcode, MYF(0),table_name);
 
1739
        goto unlock_and_end;
 
1740
    }
 
1741
  }
 
1742
 
 
1743
  session->set_proc_info("creating table");
 
1744
  create_info->table_existed= 0;                // Mark that table is created
 
1745
 
 
1746
  create_info->table_options=db_options;
 
1747
 
 
1748
  if (rea_create_table(session, path, db, table_name,
 
1749
                       table_proto,
 
1750
                       create_info, alter_info->create_list,
 
1751
                       key_count, key_info_buffer))
 
1752
    goto unlock_and_end;
 
1753
 
 
1754
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1755
  {
 
1756
    /* Open table and put in temporary table list */
 
1757
    if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
 
1758
    {
 
1759
      (void) session->rm_temporary_table(create_info->db_type, path);
 
1760
      goto unlock_and_end;
 
1761
    }
 
1762
  }
 
1763
 
 
1764
  /*
 
1765
    Don't write statement if:
 
1766
    - It is an internal temporary table,
 
1767
    - Row-based logging is used and it we are creating a temporary table, or
 
1768
    - The binary log is not open.
 
1769
    Otherwise, the statement shall be binlogged.
 
1770
   */
 
1771
  if (!internal_tmp_table &&
 
1772
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1773
    write_bin_log(session, session->query, session->query_length);
 
1774
  error= false;
 
1775
unlock_and_end:
 
1776
  pthread_mutex_unlock(&LOCK_open);
 
1777
 
 
1778
err:
 
1779
  session->set_proc_info("After create");
 
1780
  delete file;
 
1781
  return(error);
1508
1782
}
1509
1783
 
1510
1784
 
1511
1785
/*
1512
1786
  Database locking aware wrapper for mysql_create_table_no_lock(),
1513
1787
*/
1514
 
bool mysql_create_table(Session *session,
1515
 
                        const TableIdentifier &identifier,
 
1788
 
 
1789
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1516
1790
                        HA_CREATE_INFO *create_info,
1517
 
                        message::Table &table_proto,
 
1791
                        message::Table *table_proto,
1518
1792
                        AlterInfo *alter_info,
1519
1793
                        bool internal_tmp_table,
1520
 
                        uint32_t select_field_count,
1521
 
                        bool is_if_not_exists)
 
1794
                        uint32_t select_field_count)
1522
1795
{
1523
 
  if (identifier.isTmp())
1524
 
  {
1525
 
    return mysql_create_table_no_lock(session,
1526
 
                                      identifier,
1527
 
                                      create_info,
1528
 
                                      table_proto,
1529
 
                                      alter_info,
1530
 
                                      internal_tmp_table,
1531
 
                                      select_field_count,
1532
 
                                      is_if_not_exists);
1533
 
  }
1534
 
 
1535
 
  return drizzle_create_table(session,
1536
 
                              identifier,
1537
 
                              create_info,
1538
 
                              table_proto,
1539
 
                              alter_info,
1540
 
                              internal_tmp_table,
1541
 
                              select_field_count,
1542
 
                              is_if_not_exists);
 
1796
  Table *name_lock= NULL;
 
1797
  bool result;
 
1798
 
 
1799
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1800
  {
 
1801
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
1802
    {
 
1803
      result= true;
 
1804
      goto unlock;
 
1805
    }
 
1806
    if (name_lock == NULL)
 
1807
    {
 
1808
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1809
      {
 
1810
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1811
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1812
                            table_name);
 
1813
        create_info->table_existed= 1;
 
1814
        result= false;
 
1815
      }
 
1816
      else
 
1817
      {
 
1818
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1819
        result= true;
 
1820
      }
 
1821
      goto unlock;
 
1822
    }
 
1823
  }
 
1824
 
 
1825
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1826
                                     table_proto,
 
1827
                                     alter_info,
 
1828
                                     internal_tmp_table,
 
1829
                                     select_field_count);
 
1830
 
 
1831
unlock:
 
1832
  if (name_lock)
 
1833
  {
 
1834
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
 
1835
    session->unlink_open_table(name_lock);
 
1836
    pthread_mutex_unlock(&LOCK_open);
 
1837
  }
 
1838
 
 
1839
  return(result);
1543
1840
}
1544
1841
 
1545
1842
 
1548
1845
**/
1549
1846
 
1550
1847
static bool
1551
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1848
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1552
1849
{
1553
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1850
  for (KEY *key=start ; key != end ; key++)
1554
1851
    if (!my_strcasecmp(system_charset_info,name,key->name))
1555
1852
      return 1;
1556
1853
  return 0;
1558
1855
 
1559
1856
 
1560
1857
static char *
1561
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1858
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1562
1859
{
1563
1860
  char buff[MAX_FIELD_NAME],*buff_end;
1564
1861
 
1576
1873
  for (uint32_t i=2 ; i< 100; i++)
1577
1874
  {
1578
1875
    *buff_end= '_';
1579
 
    internal::int10_to_str(i, buff_end+1, 10);
 
1876
    int10_to_str(i, buff_end+1, 10);
1580
1877
    if (!check_if_keyname_exists(buff,start,end))
1581
 
      return memory::sql_strdup(buff);
 
1878
      return sql_strdup(buff);
1582
1879
  }
1583
1880
  return (char*) "not_specified";               // Should never happen
1584
1881
}
1593
1890
 
1594
1891
  SYNOPSIS
1595
1892
    mysql_rename_table()
1596
 
      session
1597
1893
      base                      The plugin::StorageEngine handle.
1598
1894
      old_db                    The old database name.
1599
1895
      old_name                  The old table name.
1600
1896
      new_db                    The new database name.
1601
1897
      new_name                  The new table name.
 
1898
      flags                     flags for build_table_filename().
 
1899
                                FN_FROM_IS_TMP old_name is temporary.
 
1900
                                FN_TO_IS_TMP   new_name is temporary.
 
1901
                                NO_FRM_RENAME  Don't rename the FRM file
 
1902
                                but only the table in the storage engine.
1602
1903
 
1603
1904
  RETURN
1604
1905
    false   OK
1606
1907
*/
1607
1908
 
1608
1909
bool
1609
 
mysql_rename_table(Session &session,
1610
 
                   plugin::StorageEngine *base,
1611
 
                   const TableIdentifier &from,
1612
 
                   const TableIdentifier &to)
 
1910
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
 
1911
                   const char *old_name, const char *new_db,
 
1912
                   const char *new_name, uint32_t flags)
1613
1913
{
 
1914
  Session *session= current_session;
 
1915
  char from[FN_REFLEN], to[FN_REFLEN];
 
1916
  char *from_base= from, *to_base= to;
1614
1917
  int error= 0;
1615
1918
 
1616
1919
  assert(base);
1617
1920
 
1618
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
1921
  build_table_filename(from, sizeof(from), old_db, old_name,
 
1922
                       flags & FN_FROM_IS_TMP);
 
1923
  build_table_filename(to, sizeof(to), new_db, new_name,
 
1924
                       flags & FN_TO_IS_TMP);
 
1925
 
 
1926
  if (!(error=base->renameTable(session, from_base, to_base)))
1619
1927
  {
1620
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1621
 
    return true;
 
1928
    if(!(flags & NO_FRM_RENAME)
 
1929
       && base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1930
       && rename_table_proto_file(from_base, to_base))
 
1931
    {
 
1932
      error= my_errno;
 
1933
      base->renameTable(session, to_base, from_base);
 
1934
    }
1622
1935
  }
1623
1936
 
1624
 
  error= base->renameTable(session, from, to);
1625
 
 
1626
1937
  if (error == HA_ERR_WRONG_COMMAND)
1627
 
  {
1628
1938
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1629
 
  }
1630
1939
  else if (error)
1631
 
  {
1632
 
    std::string from_path;
1633
 
    std::string to_path;
1634
 
 
1635
 
    from.getSQLPath(from_path);
1636
 
    to.getSQLPath(to_path);
1637
 
 
1638
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1639
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1640
 
 
1641
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1642
 
  }
1643
 
 
1644
 
  return error ? true : false; 
 
1940
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
1941
  return(error != 0);
1645
1942
}
1646
1943
 
1647
1944
 
1650
1947
 
1651
1948
  SYNOPSIS
1652
1949
    wait_while_table_is_used()
1653
 
    session                     Thread Cursor
 
1950
    session                     Thread handler
1654
1951
    table               Table to remove from cache
1655
1952
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1656
1953
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1660
1957
   the table is closed.
1661
1958
 
1662
1959
  PREREQUISITES
1663
 
    Lock on table::Cache::singleton().mutex()
 
1960
    Lock on LOCK_open
1664
1961
    Win32 clients must also have a WRITE LOCK on the table !
1665
1962
*/
1666
1963
 
1668
1965
                              enum ha_extra_function function)
1669
1966
{
1670
1967
 
1671
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1968
  safe_mutex_assert_owner(&LOCK_open);
1672
1969
 
1673
 
  table->cursor->extra(function);
 
1970
  table->file->extra(function);
1674
1971
  /* Mark all tables that are in use as 'old' */
1675
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1972
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1676
1973
 
1677
1974
  /* Wait until all there are no other threads that has this table open */
1678
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1679
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
1975
  remove_table_from_cache(session, table->s->db.str,
 
1976
                          table->s->table_name.str,
 
1977
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1680
1978
}
1681
1979
 
1682
1980
/*
1684
1982
 
1685
1983
  SYNOPSIS
1686
1984
    close_cached_table()
1687
 
    session                     Thread Cursor
 
1985
    session                     Thread handler
1688
1986
    table               Table to remove from cache
1689
1987
 
1690
1988
  NOTES
1692
1990
    reopen the table.
1693
1991
 
1694
1992
  PREREQUISITES
1695
 
    Lock on table::Cache::singleton().mutex()
 
1993
    Lock on LOCK_open
1696
1994
    Win32 clients must also have a WRITE LOCK on the table !
1697
1995
*/
1698
1996
 
1703
2001
  /* Close lock if this is not got with LOCK TABLES */
1704
2002
  if (lock)
1705
2003
  {
1706
 
    unlockTables(lock);
 
2004
    mysql_unlock_tables(this, lock);
1707
2005
    lock= NULL;                 // Start locked threads
1708
2006
  }
1709
2007
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1710
2008
  unlink_open_table(table);
1711
2009
 
1712
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1713
 
  locking::broadcast_refresh();
 
2010
  /* When lock on LOCK_open is freed other threads can continue */
 
2011
  broadcast_refresh();
1714
2012
}
1715
2013
 
1716
2014
/*
1724
2022
                              const char *operator_name,
1725
2023
                              thr_lock_type lock_type,
1726
2024
                              bool open_for_modify,
1727
 
                              int (Cursor::*operator_func)(Session *,
 
2025
                              bool no_warnings_for_error,
 
2026
                              uint32_t extra_open_options,
 
2027
                              int (*prepare_func)(Session *, TableList *,
 
2028
                                                  HA_CHECK_OPT *),
 
2029
                              int (handler::*operator_func)(Session *,
1728
2030
                                                            HA_CHECK_OPT *))
1729
2031
{
1730
2032
  TableList *table;
1733
2035
  Item *item;
1734
2036
  LEX *lex= session->lex;
1735
2037
  int result_code= 0;
1736
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1737
2038
  const CHARSET_INFO * const cs= system_charset_info;
1738
2039
 
1739
2040
  if (! session->endActiveTransaction())
1754
2055
  for (table= tables; table; table= table->next_local)
1755
2056
  {
1756
2057
    char table_name[NAME_LEN*2+2];
 
2058
    char* db = table->db;
1757
2059
    bool fatal_error=0;
1758
2060
 
1759
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
2061
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2062
    session->open_options|= extra_open_options;
1760
2063
    table->lock_type= lock_type;
1761
2064
    /* open only one table from local list of command */
1762
2065
    {
1769
2072
      /*
1770
2073
        Time zone tables and SP tables can be add to lex->query_tables list,
1771
2074
        so it have to be prepared.
1772
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2075
        TODO: Investigate if we can put extra tables into argument instead of
 
2076
        using lex->query_tables
1773
2077
      */
1774
2078
      lex->query_tables= table;
1775
2079
      lex->query_tables_last= &table->next_global;
1776
2080
      lex->query_tables_own_last= 0;
1777
 
      session->no_warnings_for_error= 0;
 
2081
      session->no_warnings_for_error= no_warnings_for_error;
1778
2082
 
1779
2083
      session->openTablesLock(table);
1780
2084
      session->no_warnings_for_error= 0;
1781
2085
      table->next_global= save_next_global;
1782
2086
      table->next_local= save_next_local;
 
2087
      session->open_options&= ~extra_open_options;
 
2088
    }
 
2089
 
 
2090
    if (prepare_func)
 
2091
    {
 
2092
      switch ((*prepare_func)(session, table, check_opt)) {
 
2093
      case  1:           // error, message written to net
 
2094
        ha_autocommit_or_rollback(session, 1);
 
2095
        session->endTransaction(ROLLBACK);
 
2096
        session->close_thread_tables();
 
2097
        continue;
 
2098
      case -1:           // error, message could be written to net
 
2099
        goto err;
 
2100
      default:           // should be 0 otherwise
 
2101
        ;
 
2102
      }
1783
2103
    }
1784
2104
 
1785
2105
    /*
1809
2129
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1810
2130
                       table_name);
1811
2131
      session->client->store(buff, length);
1812
 
      transaction_services.autocommitOrRollback(session, false);
 
2132
      ha_autocommit_or_rollback(session, 0);
1813
2133
      session->endTransaction(COMMIT);
1814
2134
      session->close_thread_tables();
1815
2135
      lex->reset_query_tables_list(false);
1820
2140
    }
1821
2141
 
1822
2142
    /* Close all instances of the table to allow repair to rename files */
1823
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2143
    if (lock_type == TL_WRITE && table->table->s->version)
1824
2144
    {
1825
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1826
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1827
 
                                                  "Waiting to get writelock");
1828
 
      session->abortLock(table->table);
1829
 
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1830
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
2145
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2146
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
2147
                                              "Waiting to get writelock");
 
2148
      mysql_lock_abort(session,table->table);
 
2149
      remove_table_from_cache(session, table->table->s->db.str,
 
2150
                              table->table->s->table_name.str,
 
2151
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2152
                              RTFC_CHECK_KILLED_FLAG);
1831
2153
      session->exit_cond(old_message);
1832
 
      if (session->getKilled())
 
2154
      if (session->killed)
1833
2155
        goto err;
1834
2156
      open_for_modify= 0;
1835
2157
    }
1836
2158
 
1837
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
2159
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2160
    {
 
2161
      session->client->store(table_name);
 
2162
      session->client->store(operator_name);
 
2163
      session->client->store(STRING_WITH_LEN("warning"));
 
2164
      session->client->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2165
      if (session->client->flush())
 
2166
        goto err;
 
2167
    }
 
2168
 
 
2169
    result_code = (table->table->file->*operator_func)(session, check_opt);
1838
2170
 
1839
2171
send_result:
1840
2172
 
1858
2190
    session->client->store(table_name);
1859
2191
    session->client->store(operator_name);
1860
2192
 
 
2193
send_result_message:
 
2194
 
1861
2195
    switch (result_code) {
1862
2196
    case HA_ADMIN_NOT_IMPLEMENTED:
1863
2197
      {
1901
2235
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1902
2236
      break;
1903
2237
 
 
2238
    case HA_ADMIN_TRY_ALTER:
 
2239
    {
 
2240
      /*
 
2241
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2242
        "try with alter", so here we close the table, do an ALTER Table,
 
2243
        reopen the table and do ha_innobase::analyze() on it.
 
2244
      */
 
2245
      ha_autocommit_or_rollback(session, 0);
 
2246
      session->close_thread_tables();
 
2247
      TableList *save_next_local= table->next_local,
 
2248
                 *save_next_global= table->next_global;
 
2249
      table->next_local= table->next_global= 0;
 
2250
      result_code= mysql_recreate_table(session, table);
 
2251
      /*
 
2252
        mysql_recreate_table() can push OK or ERROR.
 
2253
        Clear 'OK' status. If there is an error, keep it:
 
2254
        we will store the error message in a result set row
 
2255
        and then clear.
 
2256
      */
 
2257
      if (session->main_da.is_ok())
 
2258
        session->main_da.reset_diagnostics_area();
 
2259
      ha_autocommit_or_rollback(session, 0);
 
2260
      session->close_thread_tables();
 
2261
      if (!result_code) // recreation went ok
 
2262
      {
 
2263
        if ((table->table= session->openTableLock(table, lock_type)) &&
 
2264
            ((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
 
2265
          result_code= 0; // analyze went ok
 
2266
      }
 
2267
      if (result_code) // either mysql_recreate_table or analyze failed
 
2268
      {
 
2269
        assert(session->is_error());
 
2270
        if (session->is_error())
 
2271
        {
 
2272
          const char *err_msg= session->main_da.message();
 
2273
          /* Hijack the row already in-progress. */
 
2274
          session->client->store(STRING_WITH_LEN("error"));
 
2275
          session->client->store(err_msg);
 
2276
          (void)session->client->flush();
 
2277
          /* Start off another row for HA_ADMIN_FAILED */
 
2278
          session->client->store(table_name);
 
2279
          session->client->store(operator_name);
 
2280
          session->clear_error();
 
2281
        }
 
2282
      }
 
2283
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2284
      table->next_local= save_next_local;
 
2285
      table->next_global= save_next_global;
 
2286
      goto send_result_message;
 
2287
    }
 
2288
    case HA_ADMIN_NEEDS_UPGRADE:
 
2289
    case HA_ADMIN_NEEDS_ALTER:
 
2290
    {
 
2291
      char buf[ERRMSGSIZE];
 
2292
      uint32_t length;
 
2293
 
 
2294
      session->client->store(STRING_WITH_LEN("error"));
 
2295
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2296
      session->client->store(buf, length);
 
2297
      fatal_error=1;
 
2298
      break;
 
2299
    }
 
2300
 
1904
2301
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1905
2302
      {
1906
2303
        char buf[ERRMSGSIZE+20];
1916
2313
    if (table->table)
1917
2314
    {
1918
2315
      if (fatal_error)
1919
 
      {
1920
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1921
 
      }
 
2316
        table->table->s->version=0;               // Force close of table
1922
2317
      else if (open_for_modify)
1923
2318
      {
1924
 
        if (table->table->getShare()->getType())
1925
 
        {
1926
 
          table->table->cursor->info(HA_STATUS_CONST);
1927
 
        }
 
2319
        if (table->table->s->tmp_table)
 
2320
          table->table->file->info(HA_STATUS_CONST);
1928
2321
        else
1929
2322
        {
1930
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1931
 
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1932
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
2323
          pthread_mutex_lock(&LOCK_open);
 
2324
          remove_table_from_cache(session, table->table->s->db.str,
 
2325
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2326
          pthread_mutex_unlock(&LOCK_open);
1933
2327
        }
1934
2328
      }
1935
2329
    }
1936
 
    transaction_services.autocommitOrRollback(session, false);
 
2330
    ha_autocommit_or_rollback(session, 0);
1937
2331
    session->endTransaction(COMMIT);
1938
2332
    session->close_thread_tables();
1939
2333
    table->table=0;                             // For query cache
1945
2339
  return(false);
1946
2340
 
1947
2341
err:
1948
 
  transaction_services.autocommitOrRollback(session, true);
 
2342
  ha_autocommit_or_rollback(session, 1);
1949
2343
  session->endTransaction(ROLLBACK);
1950
2344
  session->close_thread_tables();                       // Shouldn't be needed
1951
2345
  if (table)
1953
2347
  return(true);
1954
2348
}
1955
2349
 
1956
 
  /*
1957
 
    Create a new table by copying from source table
1958
 
 
1959
 
    Altough exclusive name-lock on target table protects us from concurrent
1960
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
1961
 
    to plugin::StorageEngine::createTable() in critical section protected by
1962
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1963
 
    disregard name-locks, like I_S implementation, for example. This is a
1964
 
    temporary and should not be copied. Instead we should fix our code to
1965
 
    always honor name-locks.
1966
 
 
1967
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1968
 
    during the call to plugin::StorageEngine::createTable().
1969
 
    See bug #28614 for more info.
1970
 
  */
1971
 
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
 
                                 const TableIdentifier &destination_identifier,
1973
 
                                 const TableIdentifier &src_table,
1974
 
                                 bool is_engine_set)
 
2350
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
1975
2351
{
1976
 
  int protoerr= EEXIST;
1977
 
  message::Table new_proto;
1978
 
  message::table::shared_ptr src_proto;
1979
 
 
1980
 
  protoerr= plugin::StorageEngine::getTableDefinition(session,
1981
 
                                                      src_table,
1982
 
                                                      src_proto);
1983
 
  new_proto.CopyFrom(*src_proto);
1984
 
 
1985
 
  if (destination_identifier.isTmp())
1986
 
  {
1987
 
    new_proto.set_type(message::Table::TEMPORARY);
1988
 
  }
1989
 
  else
1990
 
  {
1991
 
    new_proto.set_type(message::Table::STANDARD);
1992
 
  }
1993
 
 
1994
 
  if (is_engine_set)
1995
 
  {
1996
 
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
1997
 
  }
1998
 
 
1999
 
  { // We now do a selective copy of elements on to the new table.
2000
 
    new_proto.set_name(create_table_proto.name());
2001
 
    new_proto.set_schema(create_table_proto.schema());
2002
 
    new_proto.set_catalog(create_table_proto.catalog());
2003
 
  }
2004
 
 
2005
 
  if (protoerr && protoerr != EEXIST)
2006
 
  {
2007
 
    if (errno == ENOENT)
2008
 
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2009
 
    else
2010
 
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2011
 
 
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  /*
2016
 
    As mysql_truncate don't work on a new table at this stage of
2017
 
    creation, instead create the table directly (for both normal
2018
 
    and temporary tables).
2019
 
  */
2020
 
  int err= plugin::StorageEngine::createTable(session,
2021
 
                                              destination_identifier,
2022
 
                                              new_proto);
2023
 
 
2024
 
  if (err == false && not destination_identifier.isTmp())
2025
 
  {
2026
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2027
 
    transaction_services.createTable(&session, new_proto);
2028
 
  }
2029
 
 
2030
 
  return err ? false : true;
 
2352
  return(mysql_admin_table(session, tables, check_opt,
 
2353
                           "optimize", TL_WRITE, 1,0,0,0,
 
2354
                           &handler::ha_optimize));
2031
2355
}
2032
2356
 
2033
2357
/*
2045
2369
    true  error
2046
2370
*/
2047
2371
 
2048
 
bool mysql_create_like_table(Session* session,
2049
 
                             const TableIdentifier &destination_identifier,
2050
 
                             TableList* table, TableList* src_table,
2051
 
                             message::Table &create_table_proto,
2052
 
                             bool is_if_not_exists,
2053
 
                             bool is_engine_set)
 
2372
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2373
                             drizzled::message::Table& create_table_proto,
 
2374
                             HA_CREATE_INFO *create_info)
2054
2375
{
 
2376
  Table *name_lock= 0;
 
2377
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2378
  uint32_t dst_path_length;
 
2379
  char *db= table->db;
 
2380
  char *table_name= table->table_name;
 
2381
  int  err;
2055
2382
  bool res= true;
2056
2383
  uint32_t not_used;
 
2384
  message::Table src_proto;
2057
2385
 
2058
2386
  /*
2059
2387
    By opening source table we guarantee that it exists and no concurrent
2060
2388
    DDL operation will mess with it. Later we also take an exclusive
2061
 
    name-lock on target table name, which makes copying of .frm cursor,
2062
 
    call to plugin::StorageEngine::createTable() and binlogging atomic
2063
 
    against concurrent DML and DDL operations on target table.
2064
 
    Thus by holding both these "locks" we ensure that our statement is
2065
 
    properly isolated from all concurrent operations which matter.
 
2389
    name-lock on target table name, which makes copying of .frm file,
 
2390
    call to StorageEngine::createTable() and binlogging atomic against concurrent DML
 
2391
    and DDL operations on target table. Thus by holding both these "locks"
 
2392
    we ensure that our statement is properly isolated from all concurrent
 
2393
    operations which matter.
2066
2394
  */
2067
2395
  if (session->open_tables_from_list(&src_table, &not_used))
2068
2396
    return true;
2069
2397
 
2070
 
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2071
 
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2072
 
 
 
2398
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2073
2399
 
2074
2400
 
2075
2401
  /*
2076
2402
    Check that destination tables does not exist. Note that its name
2077
2403
    was already checked when it was added to the table list.
2078
 
 
2079
 
    For temporary tables we don't aim to grab locks.
2080
 
  */
2081
 
  bool table_exists= false;
2082
 
  if (destination_identifier.isTmp())
2083
 
  {
2084
 
    if (session->find_temporary_table(destination_identifier))
2085
 
    {
2086
 
      table_exists= true;
2087
 
    }
2088
 
    else
2089
 
    {
2090
 
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
 
                                             src_identifier, is_engine_set);
2092
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2093
 
      {
2094
 
        (void) session->rm_temporary_table(destination_identifier, true);
2095
 
      }
2096
 
      else if (not session->open_temporary_table(destination_identifier))
2097
 
      {
2098
 
        // We created, but we can't open... also, a hack.
2099
 
        (void) session->rm_temporary_table(destination_identifier, true);
2100
 
      }
2101
 
      else
2102
 
      {
2103
 
        res= false;
2104
 
      }
2105
 
    }
2106
 
  }
2107
 
  else // Standard table which will require locks.
2108
 
  {
2109
 
    Table *name_lock= 0;
2110
 
 
2111
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2112
 
    {
2113
 
      if (name_lock)
2114
 
      {
2115
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2116
 
        session->unlink_open_table(name_lock);
2117
 
      }
2118
 
 
2119
 
      return res;
2120
 
    }
2121
 
 
2122
 
    if (not name_lock)
2123
 
    {
2124
 
      table_exists= true;
2125
 
    }
2126
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2127
 
    {
2128
 
      table_exists= true;
2129
 
    }
2130
 
    else // Otherwise we create the table
2131
 
    {
2132
 
      bool was_created;
2133
 
      {
2134
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2135
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2136
 
                                               src_identifier, is_engine_set);
2137
 
      }
2138
 
 
2139
 
      // So we blew the creation of the table, and we scramble to clean up
2140
 
      // anything that might have been created (read... it is a hack)
2141
 
      if (not was_created)
2142
 
      {
2143
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2144
 
      } 
2145
 
      else
2146
 
      {
2147
 
        res= false;
2148
 
      }
2149
 
    }
2150
 
 
2151
 
    if (name_lock)
2152
 
    {
2153
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2154
 
      session->unlink_open_table(name_lock);
2155
 
    }
2156
 
  }
2157
 
 
2158
 
  if (table_exists)
2159
 
  {
2160
 
    if (is_if_not_exists)
2161
 
    {
2162
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
 
      snprintf(warn_buff, sizeof(warn_buff),
2164
 
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2165
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2166
 
                   ER_TABLE_EXISTS_ERROR,warn_buff);
2167
 
      res= false;
2168
 
    }
2169
 
    else
2170
 
    {
2171
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2172
 
    }
2173
 
  }
2174
 
 
 
2404
  */
 
2405
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2406
  {
 
2407
    if (session->find_temporary_table(db, table_name))
 
2408
      goto table_exists;
 
2409
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
 
2410
  }
 
2411
  else
 
2412
  {
 
2413
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
2414
      goto err;
 
2415
    if (!name_lock)
 
2416
      goto table_exists;
 
2417
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2418
                                          db, table_name, false);
 
2419
    if (plugin::StorageEngine::getTableProto(dst_path, NULL) == EEXIST)
 
2420
      goto table_exists;
 
2421
  }
 
2422
 
 
2423
  /*
 
2424
    Create a new table by copying from source table
 
2425
 
 
2426
    Altough exclusive name-lock on target table protects us from concurrent
 
2427
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2428
    to StorageEngine::createTable() in critical section protected by LOCK_open in order
 
2429
    to provide minimal atomicity against operations which disregard name-locks,
 
2430
    like I_S implementation, for example. This is a temporary and should not
 
2431
    be copied. Instead we should fix our code to always honor name-locks.
 
2432
 
 
2433
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2434
    during the call to StorageEngine::createTable(). See bug #28614 for more info.
 
2435
  */
 
2436
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2437
  {
 
2438
    int protoerr= EEXIST;
 
2439
 
 
2440
    if (src_table->schema_table)
 
2441
    {
 
2442
      if (mysql_create_like_schema_frm(session, src_table, create_info,
 
2443
                                       &src_proto))
 
2444
      {
 
2445
        pthread_mutex_unlock(&LOCK_open);
 
2446
        goto err;
 
2447
      }
 
2448
    }
 
2449
    else
 
2450
    {
 
2451
      protoerr= plugin::StorageEngine::getTableProto(src_path, &src_proto);
 
2452
    }
 
2453
 
 
2454
    message::Table new_proto(src_proto);
 
2455
 
 
2456
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
2457
    {
 
2458
      message::Table::StorageEngine *protoengine;
 
2459
 
 
2460
      protoengine= new_proto.mutable_engine();
 
2461
      protoengine->set_name(create_table_proto.engine().name());
 
2462
    }
 
2463
 
 
2464
    string dst_proto_path(dst_path);
 
2465
    string file_ext = ".dfe";
 
2466
 
 
2467
    dst_proto_path.append(file_ext);
 
2468
 
 
2469
    if (protoerr == EEXIST)
 
2470
    {
 
2471
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(session,
 
2472
                                                                       new_proto.engine().name());
 
2473
 
 
2474
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2475
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
 
2476
      else
 
2477
        protoerr= 0;
 
2478
    }
 
2479
 
 
2480
    if (protoerr)
 
2481
    {
 
2482
      if (my_errno == ENOENT)
 
2483
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2484
      else
 
2485
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2486
      pthread_mutex_unlock(&LOCK_open);
 
2487
      goto err;
 
2488
    }
 
2489
 
 
2490
    /*
 
2491
      As mysql_truncate don't work on a new table at this stage of
 
2492
      creation, instead create the table directly (for both normal
 
2493
      and temporary tables).
 
2494
    */
 
2495
    err= plugin::StorageEngine::createTable(session, dst_path, db, table_name, create_info, 
 
2496
                                            true, &new_proto);
 
2497
  }
 
2498
  pthread_mutex_unlock(&LOCK_open);
 
2499
 
 
2500
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2501
  {
 
2502
    if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
 
2503
    {
 
2504
      (void) session->rm_temporary_table(create_info->db_type, dst_path);
 
2505
      goto err;
 
2506
    }
 
2507
  }
 
2508
  else if (err)
 
2509
  {
 
2510
    (void) quick_rm_table(create_info->db_type, db,
 
2511
                          table_name, false);
 
2512
    goto err;
 
2513
  }
 
2514
 
 
2515
  /*
 
2516
    We have to write the query before we unlock the tables.
 
2517
  */
 
2518
  {
 
2519
    /*
 
2520
       Since temporary tables are not replicated under row-based
 
2521
       replication, CREATE TABLE ... LIKE ... needs special
 
2522
       treatement.  We have four cases to consider, according to the
 
2523
       following decision table:
 
2524
 
 
2525
           ==== ========= ========= ==============================
 
2526
           Case    Target    Source Write to binary log
 
2527
           ==== ========= ========= ==============================
 
2528
           1       normal    normal Original statement
 
2529
           2       normal temporary Generated statement
 
2530
           3    temporary    normal Nothing
 
2531
           4    temporary temporary Nothing
 
2532
           ==== ========= ========= ==============================
 
2533
    */
 
2534
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2535
    {
 
2536
      if (src_table->table->s->tmp_table)               // Case 2
 
2537
      {
 
2538
        char buf[2048];
 
2539
        String query(buf, sizeof(buf), system_charset_info);
 
2540
        query.length(0);  // Have to zero it since constructor doesn't
 
2541
 
 
2542
 
 
2543
        /*
 
2544
          Here we open the destination table, on which we already have
 
2545
          name-lock. This is needed for store_create_info() to work.
 
2546
          The table will be closed by unlink_open_table() at the end
 
2547
          of this function.
 
2548
        */
 
2549
        table->table= name_lock;
 
2550
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2551
        if (session->reopen_name_locked_table(table, false))
 
2552
        {
 
2553
          pthread_mutex_unlock(&LOCK_open);
 
2554
          goto err;
 
2555
        }
 
2556
        pthread_mutex_unlock(&LOCK_open);
 
2557
 
 
2558
        int result= store_create_info(table, &query, create_info);
 
2559
 
 
2560
        assert(result == 0); // store_create_info() always return 0
 
2561
        write_bin_log(session, query.ptr(), query.length());
 
2562
      }
 
2563
      else                                      // Case 1
 
2564
        write_bin_log(session, session->query, session->query_length);
 
2565
    }
 
2566
  }
 
2567
 
 
2568
  res= false;
 
2569
  goto err;
 
2570
 
 
2571
table_exists:
 
2572
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2573
  {
 
2574
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2575
    snprintf(warn_buff, sizeof(warn_buff),
 
2576
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2577
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2578
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2579
    res= false;
 
2580
  }
 
2581
  else
 
2582
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2583
 
 
2584
err:
 
2585
  if (name_lock)
 
2586
  {
 
2587
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2588
    session->unlink_open_table(name_lock);
 
2589
    pthread_mutex_unlock(&LOCK_open);
 
2590
  }
2175
2591
  return(res);
2176
2592
}
2177
2593
 
2181
2597
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2182
2598
 
2183
2599
  return(mysql_admin_table(session, tables, check_opt,
2184
 
                                "analyze", lock_type, true,
2185
 
                                &Cursor::ha_analyze));
 
2600
                                "analyze", lock_type, 1, 0, 0, 0,
 
2601
                                &handler::ha_analyze));
2186
2602
}
2187
2603
 
2188
2604
 
2192
2608
 
2193
2609
  return(mysql_admin_table(session, tables, check_opt,
2194
2610
                                "check", lock_type,
2195
 
                                false,
2196
 
                                &Cursor::ha_check));
2197
 
}
2198
 
 
2199
 
} /* namespace drizzled */
 
2611
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
2612
                                &handler::ha_check));
 
2613
}
 
2614
 
 
2615
/*
 
2616
  Recreates tables by calling mysql_alter_table().
 
2617
 
 
2618
  SYNOPSIS
 
2619
    mysql_recreate_table()
 
2620
    session                     Thread handler
 
2621
    tables              Tables to recreate
 
2622
 
 
2623
 RETURN
 
2624
    Like mysql_alter_table().
 
2625
*/
 
2626
bool mysql_recreate_table(Session *session, TableList *table_list)
 
2627
{
 
2628
  HA_CREATE_INFO create_info;
 
2629
  AlterInfo alter_info;
 
2630
  message::Table table_proto;
 
2631
 
 
2632
  assert(!table_list->next_global);
 
2633
  /*
 
2634
    table_list->table has been closed and freed. Do not reference
 
2635
    uninitialized data. open_tables() could fail.
 
2636
  */
 
2637
  table_list->table= NULL;
 
2638
 
 
2639
  memset(&create_info, 0, sizeof(create_info));
 
2640
  create_info.row_type=ROW_TYPE_NOT_USED;
 
2641
  create_info.default_table_charset=default_charset_info;
 
2642
  /* Force alter table to recreate table */
 
2643
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
2644
  alter_info.flags.set(ALTER_RECREATE);
 
2645
  return(mysql_alter_table(session, NULL, NULL, &create_info, &table_proto,
 
2646
                           table_list, &alter_info, 0,
 
2647
                           (order_st *) 0, 0));
 
2648
}
 
2649
 
 
2650
 
 
2651
bool mysql_checksum_table(Session *session, TableList *tables,
 
2652
                          HA_CHECK_OPT *check_opt)
 
2653
{
 
2654
  TableList *table;
 
2655
  List<Item> field_list;
 
2656
  Item *item;
 
2657
 
 
2658
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
2659
  item->maybe_null= 1;
 
2660
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
2661
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
2662
  item->maybe_null= 1;
 
2663
  if (session->client->sendFields(&field_list))
 
2664
    return true;
 
2665
 
 
2666
  /* Open one table after the other to keep lock time as short as possible. */
 
2667
  for (table= tables; table; table= table->next_local)
 
2668
  {
 
2669
    char table_name[NAME_LEN*2+2];
 
2670
    Table *t;
 
2671
 
 
2672
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2673
 
 
2674
    t= table->table= session->openTableLock(table, TL_READ);
 
2675
    session->clear_error();                     // these errors shouldn't get client
 
2676
 
 
2677
    session->client->store(table_name);
 
2678
 
 
2679
    if (!t)
 
2680
    {
 
2681
      /* Table didn't exist */
 
2682
      session->client->store();
 
2683
      session->clear_error();
 
2684
    }
 
2685
    else
 
2686
    {
 
2687
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
2688
          !(check_opt->flags & T_EXTEND))
 
2689
        session->client->store((uint64_t)t->file->checksum());
 
2690
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
2691
               (check_opt->flags & T_QUICK))
 
2692
        session->client->store();
 
2693
      else
 
2694
      {
 
2695
        /* calculating table's checksum */
 
2696
        ha_checksum crc= 0;
 
2697
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2698
 
 
2699
        t->use_all_columns();
 
2700
 
 
2701
        if (t->file->ha_rnd_init(1))
 
2702
          session->client->store();
 
2703
        else
 
2704
        {
 
2705
          for (;;)
 
2706
          {
 
2707
            ha_checksum row_crc= 0;
 
2708
            int error= t->file->rnd_next(t->record[0]);
 
2709
            if (unlikely(error))
 
2710
            {
 
2711
              if (error == HA_ERR_RECORD_DELETED)
 
2712
                continue;
 
2713
              break;
 
2714
            }
 
2715
            if (t->s->null_bytes)
 
2716
            {
 
2717
              /* fix undefined null bits */
 
2718
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
2719
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
2720
                t->record[0][0] |= 1;
 
2721
 
 
2722
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
2723
            }
 
2724
 
 
2725
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
2726
            {
 
2727
              Field *f= t->field[i];
 
2728
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
2729
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
2730
              {
 
2731
                String tmp;
 
2732
                f->val_str(&tmp);
 
2733
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
2734
              }
 
2735
              else
 
2736
                row_crc= my_checksum(row_crc, f->ptr,
 
2737
                                     f->pack_length());
 
2738
            }
 
2739
 
 
2740
            crc+= row_crc;
 
2741
          }
 
2742
          session->client->store((uint64_t)crc);
 
2743
          t->file->ha_rnd_end();
 
2744
        }
 
2745
      }
 
2746
      session->clear_error();
 
2747
      session->close_thread_tables();
 
2748
      table->table=0;                           // For query cache
 
2749
    }
 
2750
    if (session->client->flush())
 
2751
      goto err;
 
2752
  }
 
2753
 
 
2754
  session->my_eof();
 
2755
  return(false);
 
2756
 
 
2757
 err:
 
2758
  session->close_thread_tables();                       // Shouldn't be needed
 
2759
  if (table)
 
2760
    table->table=0;
 
2761
  return(true);
 
2762
}
 
2763
 
 
2764
bool check_engine(Session *session, const char *table_name,
 
2765
                         HA_CREATE_INFO *create_info)
 
2766
{
 
2767
  plugin::StorageEngine **new_engine= &create_info->db_type;
 
2768
  plugin::StorageEngine *req_engine= *new_engine;
 
2769
  if (!req_engine->is_enabled())
 
2770
  {
 
2771
    string engine_name= req_engine->getName();
 
2772
    my_error(ER_FEATURE_DISABLED,MYF(0),
 
2773
             engine_name.c_str(), engine_name.c_str());
 
2774
             
 
2775
    return true;
 
2776
  }
 
2777
 
 
2778
  if (req_engine && req_engine != *new_engine)
 
2779
  {
 
2780
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2781
                       ER_WARN_USING_OTHER_HANDLER,
 
2782
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
2783
                       plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2784
                       table_name);
 
2785
  }
 
2786
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
2787
      (*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
 
2788
  {
 
2789
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
2790
    {
 
2791
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2792
               plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2793
               "TEMPORARY");
 
2794
      *new_engine= 0;
 
2795
      return true;
 
2796
    }
 
2797
    *new_engine= myisam_engine;
 
2798
  }
 
2799
  if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2800
     && (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
 
2801
  {
 
2802
    my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2803
             plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2804
             "non-TEMPORARY");
 
2805
    *new_engine= 0;
 
2806
    return true;
 
2807
  }
 
2808
 
 
2809
  return false;
 
2810
}