~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

Merged in latest plugin-slot-reorg.

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"
50
 
#include "drizzled/plugin/storage_engine.h"
 
37
 
 
38
#include "drizzled/statement/alter_table.h" /* for mysql_create_like_schema_frm, which will die soon */
51
39
 
52
40
#include <algorithm>
53
 
#include <sstream>
54
 
 
55
 
#include <boost/unordered_set.hpp>
56
41
 
57
42
using namespace std;
58
 
 
59
 
namespace drizzled
60
 
{
61
 
 
62
 
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)
63
47
{
64
48
  static const char * primary_key_name="PRIMARY";
65
49
  return (strcmp(key_info->name, primary_key_name)==0);
74
58
    return NULL;
75
59
}
76
60
 
77
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
78
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
 
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);
79
63
 
80
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
65
 
82
 
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)
83
67
{
84
68
  /*
85
69
    If the table character set was not given explicitly,
86
70
    let's fetch the database default character set and
87
71
    apply it to the table.
88
72
  */
89
 
  identifier::Schema identifier(db);
90
73
  if (create_info->default_table_charset == NULL)
91
 
    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;
92
311
}
93
312
 
94
313
/*
95
314
  SYNOPSIS
96
315
    write_bin_log()
97
316
    session                           Thread object
 
317
    clear_error                   is clear_error to be called
98
318
    query                         Query to log
99
319
    query_length                  Length of query
100
320
 
103
323
 
104
324
  DESCRIPTION
105
325
    Write the binlog if open, routine used in multiple places in this
106
 
    cursor
107
 
*/
108
 
 
109
 
void write_bin_log(Session *session, const std::string &query)
110
 
{
111
 
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
 
326
    file
 
327
*/
 
328
 
 
329
void write_bin_log(Session *session, bool,
 
330
                   char const *query, size_t query_length)
 
331
{
 
332
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
333
  replication_services.rawStatement(session, query, query_length);
 
334
}
 
335
 
 
336
 
 
337
/*
 
338
 delete (drop) tables.
 
339
 
 
340
  SYNOPSIS
 
341
   mysql_rm_table()
 
342
   session                      Thread handle
 
343
   tables               List of tables to delete
 
344
   if_exists            If 1, don't give error if one table doesn't exists
 
345
 
 
346
  NOTES
 
347
    Will delete all tables that can be deleted and give a compact error
 
348
    messages for tables that could not be deleted.
 
349
    If a table is in use, we will wait for all users to free the table
 
350
    before dropping it
 
351
 
 
352
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
353
    not if under LOCK TABLES.
 
354
 
 
355
  RETURN
 
356
    false OK.  In this case ok packet is sent to user
 
357
    true  Error
 
358
 
 
359
*/
 
360
 
 
361
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
 
362
{
 
363
  bool error, need_start_waiting= false;
 
364
 
 
365
  if (tables && tables->schema_table)
 
366
  {
 
367
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
368
    return(true);
 
369
  }
 
370
 
 
371
  /* mark for close and remove all cached entries */
 
372
 
 
373
  if (!drop_temporary)
 
374
  {
 
375
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
376
      return(true);
 
377
  }
 
378
 
 
379
  /*
 
380
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
381
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
382
    close their tables. This would make a pretty deadlock.
 
383
  */
 
384
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, 0);
 
385
 
 
386
  if (need_start_waiting)
 
387
    start_waiting_global_read_lock(session);
 
388
 
 
389
  if (error)
 
390
    return(true);
 
391
  session->my_ok();
 
392
  return(false);
113
393
}
114
394
 
115
395
/*
116
396
  Execute the drop of a normal or temporary table
117
397
 
118
398
  SYNOPSIS
119
 
    rm_table_part2()
120
 
    session                     Thread Cursor
 
399
    mysql_rm_table_part2()
 
400
    session                     Thread handler
121
401
    tables              Tables to drop
122
402
    if_exists           If set, don't give an error if table doesn't exists.
123
403
                        In this case we give an warning of level 'NOTE'
124
404
    drop_temporary      Only drop temporary tables
 
405
    drop_view           Allow to delete VIEW .frm
 
406
    dont_log_query      Don't write query to log files. This will also not
 
407
                        generate warnings if the handler files doesn't exists
125
408
 
126
 
  @todo
 
409
  TODO:
127
410
    When logging to the binary log, we should log
128
411
    tmp_tables and transactional tables as separate statements if we
129
412
    are in a transaction;  This is needed to get these tables into the
139
422
   -1   Thread was killed
140
423
*/
141
424
 
142
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                   bool drop_temporary)
 
425
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
426
                         bool drop_temporary, bool dont_log_query)
144
427
{
145
428
  TableList *table;
 
429
  char path[FN_REFLEN];
 
430
  uint32_t path_length= 0;
146
431
  String wrong_tables;
147
432
  int error= 0;
148
 
  bool foreign_key_error= false;
149
 
 
150
 
  do
151
 
  {
152
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
153
 
 
154
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
 
    {
156
 
      return 1;
157
 
    }
158
 
 
159
 
    /* Don't give warnings for not found errors, as we already generate notes */
160
 
    session->no_warnings_for_error= 1;
161
 
 
162
 
    for (table= tables; table; table= table->next_local)
163
 
    {
164
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
165
 
 
166
 
      error= session->drop_temporary_table(tmp_identifier);
167
 
 
168
 
      switch (error) {
169
 
      case  0:
170
 
        // removed temporary table
171
 
        continue;
172
 
      case -1:
 
433
  int non_temp_tables_count= 0;
 
434
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
 
435
  String built_query;
 
436
 
 
437
  if (!dont_log_query)
 
438
  {
 
439
    built_query.set_charset(system_charset_info);
 
440
    if (if_exists)
 
441
      built_query.append("DROP Table IF EXISTS ");
 
442
    else
 
443
      built_query.append("DROP Table ");
 
444
  }
 
445
 
 
446
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
447
 
 
448
  /*
 
449
    If we have the table in the definition cache, we don't have to check the
 
450
    .frm file to find if the table is a normal table (not view) and what
 
451
    engine to use.
 
452
  */
 
453
 
 
454
  for (table= tables; table; table= table->next_local)
 
455
  {
 
456
    TableShare *share;
 
457
    table->db_type= NULL;
 
458
    if ((share= TableShare::getShare(table->db, table->table_name)))
 
459
      table->db_type= share->db_type();
 
460
  }
 
461
 
 
462
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
463
  {
 
464
    pthread_mutex_unlock(&LOCK_open);
 
465
    return 1;
 
466
  }
 
467
 
 
468
  /* Don't give warnings for not found errors, as we already generate notes */
 
469
  session->no_warnings_for_error= 1;
 
470
 
 
471
  for (table= tables; table; table= table->next_local)
 
472
  {
 
473
    char *db=table->db;
 
474
    plugin::StorageEngine *table_type;
 
475
 
 
476
    error= session->drop_temporary_table(table);
 
477
 
 
478
    switch (error) {
 
479
    case  0:
 
480
      // removed temporary table
 
481
      tmp_table_deleted= 1;
 
482
      continue;
 
483
    case -1:
 
484
      error= 1;
 
485
      goto err_with_placeholders;
 
486
    default:
 
487
      // temporary table not found
 
488
      error= 0;
 
489
    }
 
490
 
 
491
    /*
 
492
      If row-based replication is used and the table is not a
 
493
      temporary table, we add the table name to the drop statement
 
494
      being built.  The string always end in a comma and the comma
 
495
      will be chopped off before being written to the binary log.
 
496
      */
 
497
    if (!dont_log_query)
 
498
    {
 
499
      non_temp_tables_count++;
 
500
      /*
 
501
        Don't write the database name if it is the current one (or if
 
502
        session->db is NULL).
 
503
      */
 
504
      built_query.append("`");
 
505
      if (session->db == NULL || strcmp(db,session->db) != 0)
 
506
      {
 
507
        built_query.append(db);
 
508
        built_query.append("`.`");
 
509
      }
 
510
 
 
511
      built_query.append(table->table_name);
 
512
      built_query.append("`,");
 
513
    }
 
514
 
 
515
    table_type= table->db_type;
 
516
    if (!drop_temporary)
 
517
    {
 
518
      Table *locked_table;
 
519
      abort_locked_tables(session, db, table->table_name);
 
520
      remove_table_from_cache(session, db, table->table_name,
 
521
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
522
                              RTFC_CHECK_KILLED_FLAG);
 
523
      /*
 
524
        If the table was used in lock tables, remember it so that
 
525
        unlock_table_names can free it
 
526
      */
 
527
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
528
        table->table= locked_table;
 
529
 
 
530
      if (session->killed)
 
531
      {
 
532
        error= -1;
 
533
        goto err_with_placeholders;
 
534
      }
 
535
      /* remove .frm file and engine files */
 
536
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
 
537
    }
 
538
    plugin::Registry &plugins= plugin::Registry::singleton();
 
539
    if (drop_temporary ||
 
540
        ((table_type == NULL
 
541
          && (plugins.storage_engine.getTableProto(path, NULL) != EEXIST))))
 
542
    {
 
543
      // Table was not found on disk and table can't be created from engine
 
544
      if (if_exists)
 
545
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
546
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
547
                            table->table_name);
 
548
      else
173
549
        error= 1;
174
 
        break;
175
 
      default:
176
 
        // temporary table not found
177
 
        error= 0;
178
 
      }
179
 
 
180
 
      if (drop_temporary == false)
181
 
      {
182
 
        Table *locked_table;
183
 
        abort_locked_tables(session, tmp_identifier);
184
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
185
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
186
 
                                              RTFC_CHECK_KILLED_FLAG);
187
 
        /*
188
 
          If the table was used in lock tables, remember it so that
189
 
          unlock_table_names can free it
190
 
        */
191
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
192
 
          table->table= locked_table;
193
 
 
194
 
        if (session->getKilled())
195
 
        {
196
 
          error= -1;
197
 
          break;
198
 
        }
199
 
      }
200
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
201
 
 
202
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
203
 
      {
204
 
        // Table was not found on disk and table can't be created from engine
205
 
        if (if_exists)
206
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
 
                              table->getTableName());
209
 
        else
210
 
        {
211
 
          error= 1;
212
 
        }
213
 
      }
214
 
      else
215
 
      {
216
 
        drizzled::error_t local_error;
217
 
 
218
 
        /* Generate transaction event ONLY when we successfully drop */ 
219
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
220
 
        {
221
 
          TransactionServices &transaction_services= TransactionServices::singleton();
222
 
          transaction_services.dropTable(*session, identifier, if_exists);
223
 
        }
224
 
        else
225
 
        {
226
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
227
 
          {
228
 
            error= 0;
229
 
            session->clear_error();
230
 
          }
231
 
 
232
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
233
 
          {
234
 
            /* the table is referenced by a foreign key constraint */
235
 
            foreign_key_error= true;
236
 
          }
237
 
          error= local_error;
238
 
        }
239
 
      }
240
 
 
241
 
      if (error)
242
 
      {
243
 
        if (wrong_tables.length())
244
 
          wrong_tables.append(',');
245
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
246
 
      }
247
 
    }
248
 
 
249
 
    tables->unlock_table_names();
250
 
 
251
 
  } while (0);
252
 
 
 
550
    }
 
551
    else
 
552
    {
 
553
      error= ha_delete_table(session, path, db, table->table_name,
 
554
                             !dont_log_query);
 
555
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
 
556
          if_exists)
 
557
      {
 
558
        error= 0;
 
559
        session->clear_error();
 
560
      }
 
561
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
562
      {
 
563
        /* the table is referenced by a foreign key constraint */
 
564
        foreign_key_error=1;
 
565
      }
 
566
      if (error == 0)
 
567
      {
 
568
          some_tables_deleted=1;
 
569
      }
 
570
    }
 
571
    if (error)
 
572
    {
 
573
      if (wrong_tables.length())
 
574
        wrong_tables.append(',');
 
575
      wrong_tables.append(String(table->table_name,system_charset_info));
 
576
    }
 
577
  }
 
578
  /*
 
579
    It's safe to unlock LOCK_open: we have an exclusive lock
 
580
    on the table name.
 
581
  */
 
582
  pthread_mutex_unlock(&LOCK_open);
 
583
  error= 0;
253
584
  if (wrong_tables.length())
254
585
  {
255
 
    if (not foreign_key_error)
256
 
    {
 
586
    if (!foreign_key_error)
257
587
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
588
                      wrong_tables.c_ptr());
259
 
    }
260
589
    else
261
590
    {
262
591
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
264
593
    error= 1;
265
594
  }
266
595
 
 
596
  if (some_tables_deleted || tmp_table_deleted || !error)
 
597
  {
 
598
    if (!dont_log_query)
 
599
    {
 
600
      if ((non_temp_tables_count > 0 && !tmp_table_deleted))
 
601
      {
 
602
        /*
 
603
          In this case, we are either using statement-based
 
604
          replication or using row-based replication but have only
 
605
          deleted one or more non-temporary tables (and no temporary
 
606
          tables).  In this case, we can write the original query into
 
607
          the binary log.
 
608
         */
 
609
        write_bin_log(session, !error, session->query, session->query_length);
 
610
      }
 
611
      else if (non_temp_tables_count > 0 &&
 
612
               tmp_table_deleted)
 
613
      {
 
614
        /*
 
615
          In this case we have deleted both temporary and
 
616
          non-temporary tables, so:
 
617
          - since we have deleted a non-temporary table we have to
 
618
            binlog the statement, but
 
619
          - since we have deleted a temporary table we cannot binlog
 
620
            the statement (since the table has not been created on the
 
621
            slave, this might cause the slave to stop).
 
622
 
 
623
          Instead, we write a built statement, only containing the
 
624
          non-temporary tables, to the binary log
 
625
        */
 
626
        built_query.chop();                  // Chop of the last comma
 
627
        built_query.append(" /* generated by server */");
 
628
        write_bin_log(session, !error, built_query.ptr(), built_query.length());
 
629
      }
 
630
      /*
 
631
        The remaining cases are:
 
632
        - no tables where deleted and
 
633
        - only temporary tables where deleted and row-based
 
634
          replication is used.
 
635
        In both these cases, nothing should be written to the binary
 
636
        log.
 
637
      */
 
638
    }
 
639
  }
 
640
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
 
641
err_with_placeholders:
 
642
  unlock_table_names(tables, NULL);
 
643
  pthread_mutex_unlock(&LOCK_open);
267
644
  session->no_warnings_for_error= 0;
268
645
 
269
 
  return error;
 
646
  return(error);
 
647
}
 
648
 
 
649
 
 
650
/*
 
651
  Quickly remove a table.
 
652
 
 
653
  SYNOPSIS
 
654
    quick_rm_table()
 
655
      base                      The plugin::StorageEngine handle.
 
656
      db                        The database name.
 
657
      table_name                The table name.
 
658
      is_tmp                    If the table is temp.
 
659
 
 
660
  RETURN
 
661
    0           OK
 
662
    != 0        Error
 
663
*/
 
664
 
 
665
bool quick_rm_table(plugin::StorageEngine *, const char *db,
 
666
                    const char *table_name, bool is_tmp)
 
667
{
 
668
  char path[FN_REFLEN];
 
669
  bool error= 0;
 
670
 
 
671
  build_table_filename(path, sizeof(path), db, table_name, is_tmp);
 
672
 
 
673
  return(ha_delete_table(current_session, path, db, table_name, 0) ||
 
674
              error);
270
675
}
271
676
 
272
677
/*
282
687
  PRIMARY keys are prioritized.
283
688
*/
284
689
 
285
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
690
static int sort_keys(KEY *a, KEY *b)
286
691
{
287
692
  ulong a_flags= a->flags, b_flags= b->flags;
288
693
 
334
739
    1             Error
335
740
*/
336
741
 
337
 
class typelib_set_member
338
 
{
339
 
public:
340
 
  string s;
341
 
  const CHARSET_INFO * const cs;
342
 
 
343
 
  typelib_set_member(const char* value, unsigned int length,
344
 
                     const CHARSET_INFO * const charset)
345
 
    : s(value, length),
346
 
      cs(charset)
347
 
  {}
348
 
};
349
 
 
350
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
351
 
{
352
 
  return (my_strnncoll(a.cs,
353
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
354
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
355
 
}
356
 
 
357
 
 
358
 
namespace
359
 
{
360
 
class typelib_set_member_hasher
361
 
{
362
 
  boost::hash<string> hasher;
363
 
public:
364
 
  std::size_t operator()(const typelib_set_member& t) const
365
 
  {
366
 
    return hasher(t.s);
367
 
  }
368
 
};
369
 
}
370
 
 
371
742
static bool check_duplicates_in_interval(const char *set_or_name,
372
743
                                         const char *name, TYPELIB *typelib,
373
744
                                         const CHARSET_INFO * const cs,
378
749
  unsigned int *cur_length= typelib->type_lengths;
379
750
  *dup_val_count= 0;
380
751
 
381
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
382
 
 
383
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
752
  for ( ; tmp.count > 1; cur_value++, cur_length++)
384
753
  {
385
754
    tmp.type_names++;
386
755
    tmp.type_lengths++;
387
756
    tmp.count--;
388
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
757
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
389
758
    {
390
759
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
760
               name,*cur_value,set_or_name);
392
761
      return 1;
393
762
    }
394
 
    else
395
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
396
763
  }
397
764
  return 0;
398
765
}
441
808
    sql_field     field to prepare for packing
442
809
    blob_columns  count for BLOBs
443
810
    timestamps    count for timestamps
 
811
    table_flags   table flags
444
812
 
445
813
  DESCRIPTION
446
814
    This function prepares a CreateField instance.
452
820
*/
453
821
int prepare_create_field(CreateField *sql_field,
454
822
                         uint32_t *blob_columns,
455
 
                         int *timestamps,
456
 
                         int *timestamps_with_niladic)
 
823
                         int *timestamps, int *timestamps_with_niladic,
 
824
                         int64_t )
457
825
{
458
826
  unsigned int dup_val_count;
459
827
 
465
833
 
466
834
  switch (sql_field->sql_type) {
467
835
  case DRIZZLE_TYPE_BLOB:
468
 
    sql_field->length= 8; // Unireg field length
 
836
    sql_field->pack_flag=FIELDFLAG_BLOB |
 
837
      pack_length_to_packflag(sql_field->pack_length -
 
838
                              portable_sizeof_char_ptr);
 
839
    if (sql_field->charset->state & MY_CS_BINSORT)
 
840
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
841
    sql_field->length=8;                        // Unireg field length
469
842
    (*blob_columns)++;
470
843
    break;
471
 
 
 
844
  case DRIZZLE_TYPE_VARCHAR:
 
845
    sql_field->pack_flag=0;
 
846
    if (sql_field->charset->state & MY_CS_BINSORT)
 
847
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
848
    break;
472
849
  case DRIZZLE_TYPE_ENUM:
473
 
    {
474
 
      if (check_duplicates_in_interval("ENUM",
475
 
                                       sql_field->field_name,
476
 
                                       sql_field->interval,
477
 
                                       sql_field->charset,
478
 
                                       &dup_val_count))
479
 
      {
480
 
        return 1;
481
 
      }
482
 
    }
483
 
    break;
484
 
 
485
 
  case DRIZZLE_TYPE_MICROTIME:
 
850
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
851
      FIELDFLAG_INTERVAL;
 
852
    if (sql_field->charset->state & MY_CS_BINSORT)
 
853
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
854
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
 
855
                                 sql_field->interval,
 
856
                                     sql_field->charset, &dup_val_count))
 
857
      return 1;
 
858
    break;
 
859
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
860
  case DRIZZLE_TYPE_DATETIME:
 
861
  case DRIZZLE_TYPE_NULL:
 
862
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
 
863
    break;
 
864
  case DRIZZLE_TYPE_NEWDECIMAL:
 
865
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
866
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
867
                           FIELDFLAG_DECIMAL) |
 
868
                          (sql_field->flags & DECIMAL_FLAG ?  FIELDFLAG_DECIMAL_POSITION : 0) |
 
869
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
 
870
    break;
486
871
  case DRIZZLE_TYPE_TIMESTAMP:
487
872
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
873
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
493
878
        (*timestamps_with_niladic)++;
494
879
      }
495
880
      else
496
 
      {
497
881
        sql_field->unireg_check= Field::NONE;
498
 
      }
499
882
    }
500
883
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
884
      (*timestamps_with_niladic)++;
503
 
    }
504
885
 
505
886
    (*timestamps)++;
506
 
 
507
 
    break;
508
 
 
509
 
  case DRIZZLE_TYPE_BOOLEAN:
510
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
511
 
  case DRIZZLE_TYPE_DATETIME:
512
 
  case DRIZZLE_TYPE_DECIMAL:
513
 
  case DRIZZLE_TYPE_DOUBLE:
514
 
  case DRIZZLE_TYPE_LONG:
515
 
  case DRIZZLE_TYPE_LONGLONG:
516
 
  case DRIZZLE_TYPE_NULL:
517
 
  case DRIZZLE_TYPE_TIME:
518
 
  case DRIZZLE_TYPE_UUID:
519
 
  case DRIZZLE_TYPE_VARCHAR:
 
887
    /* fall-through */
 
888
  default:
 
889
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
890
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
891
                           FIELDFLAG_DECIMAL) |
 
892
                          f_settype((uint32_t) sql_field->sql_type) |
 
893
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
520
894
    break;
521
895
  }
522
 
 
 
896
  if (!(sql_field->flags & NOT_NULL_FLAG))
 
897
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
 
898
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
 
899
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
523
900
  return 0;
524
901
}
525
902
 
526
 
static int prepare_create_table(Session *session,
527
 
                                HA_CREATE_INFO *create_info,
528
 
                                message::Table &create_proto,
529
 
                                AlterInfo *alter_info,
530
 
                                bool tmp_table,
531
 
                                uint32_t *db_options,
532
 
                                KeyInfo **key_info_buffer,
533
 
                                uint32_t *key_count,
534
 
                                int select_field_count)
 
903
int mysql_prepare_create_table(Session *session,
 
904
                               HA_CREATE_INFO *create_info,
 
905
                               AlterInfo *alter_info,
 
906
                               bool tmp_table,
 
907
                               uint32_t *db_options,
 
908
                               handler *file,
 
909
                               KEY **key_info_buffer,
 
910
                               uint32_t *key_count,
 
911
                               int select_field_count)
535
912
{
536
913
  const char    *key_name;
537
914
  CreateField   *sql_field,*dup_field;
538
915
  uint          field,null_fields,blob_columns,max_key_length;
539
916
  ulong         record_offset= 0;
540
 
  KeyInfo               *key_info;
541
 
  KeyPartInfo *key_part_info;
 
917
  KEY           *key_info;
 
918
  KEY_PART_INFO *key_part_info;
542
919
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
920
  int           field_no,dup_no;
544
921
  int           select_field_pos,auto_increment=0;
545
922
  List_iterator<CreateField> it(alter_info->create_list);
546
923
  List_iterator<CreateField> it2(alter_info->create_list);
547
924
  uint32_t total_uneven_bit_length= 0;
548
925
 
549
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
550
 
 
551
926
  select_field_pos= alter_info->create_list.elements - select_field_count;
552
927
  null_fields=blob_columns=0;
553
 
  max_key_length= engine->max_key_length();
 
928
  max_key_length= file->max_key_length();
554
929
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
930
  for (field_no=0; (sql_field=it++) ; field_no++)
556
931
  {
557
932
    const CHARSET_INFO *save_cs;
558
933
 
562
937
      executing a prepared statement for the second time.
563
938
    */
564
939
    sql_field->length= sql_field->char_length;
565
 
 
566
940
    if (!sql_field->charset)
567
941
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
942
    /*
570
943
      table_charset is set in ALTER Table if we want change character set
571
944
      for all varchar/char columns.
618
991
 
619
992
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
993
    {
621
 
      size_t dummy;
 
994
      uint32_t dummy;
622
995
      const CHARSET_INFO * const cs= sql_field->charset;
623
996
      TYPELIB *interval= sql_field->interval;
624
997
 
651
1024
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
1025
                                       cs, &dummy))
653
1026
          {
654
 
            size_t cnv_errs;
 
1027
            uint32_t cnv_errs;
655
1028
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
656
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
1029
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
1030
                                                  conv.length());
657
1031
            interval->type_lengths[i]= conv.length();
658
1032
          }
659
1033
 
693
1067
            }
694
1068
          }
695
1069
        }
696
 
        uint32_t new_dummy;
697
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
1070
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
698
1071
        sql_field->length= field_length;
699
1072
      }
700
1073
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
758
1131
        }
759
1132
      }
760
1133
    }
761
 
 
762
 
    /** @todo Get rid of this MyISAM-specific crap. */
763
 
    if (not create_proto.engine().name().compare("MyISAM") &&
764
 
        ((sql_field->flags & BLOB_FLAG) ||
765
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
766
 
    {
 
1134
    /* Don't pack rows in old tables if the user has requested this */
 
1135
    if ((sql_field->flags & BLOB_FLAG) ||
 
1136
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
767
1137
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
1138
    it2.rewind();
771
1139
  }
772
1140
 
780
1148
    assert(sql_field->charset != 0);
781
1149
 
782
1150
    if (prepare_create_field(sql_field, &blob_columns,
783
 
                             &timestamps, &timestamps_with_niladic))
 
1151
                             &timestamps, &timestamps_with_niladic,
 
1152
                             file->ha_table_flags()))
784
1153
      return(true);
785
1154
    sql_field->offset= record_offset;
786
1155
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
798
1167
    return(true);
799
1168
  }
800
1169
  if (auto_increment &&
801
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1170
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
802
1171
  {
803
1172
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
804
1173
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
805
1174
    return(true);
806
1175
  }
807
1176
 
808
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1177
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
809
1178
  {
810
1179
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
811
1180
               MYF(0));
833
1202
      fk_key_count++;
834
1203
      if (((Foreign_key *)key)->validate(alter_info->create_list))
835
1204
        return true;
836
 
 
837
1205
      Foreign_key *fk_key= (Foreign_key*) key;
838
 
 
839
 
      add_foreign_key_to_table_message(&create_proto,
840
 
                                       fk_key->name.str,
841
 
                                       fk_key->columns,
842
 
                                       fk_key->ref_table,
843
 
                                       fk_key->ref_columns,
844
 
                                       fk_key->delete_opt,
845
 
                                       fk_key->update_opt,
846
 
                                       fk_key->match_opt);
847
 
 
848
1206
      if (fk_key->ref_columns.elements &&
849
1207
          fk_key->ref_columns.elements != fk_key->columns.elements)
850
1208
      {
857
1215
      continue;
858
1216
    }
859
1217
    (*key_count)++;
860
 
    tmp= engine->max_key_parts();
 
1218
    tmp=file->max_key_parts();
861
1219
    if (key->columns.elements > tmp)
862
1220
    {
863
1221
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
879
1237
             key2->name.str != ignore_key &&
880
1238
             !foreign_key_prefix(key, key2)))
881
1239
        {
882
 
          /* @todo issue warning message */
 
1240
          /* TODO: issue warning message */
883
1241
          /* mark that the generated key should be ignored */
884
1242
          if (!key2->generated ||
885
1243
              (key->generated && key->columns.elements <
906
1264
      return(true);
907
1265
    }
908
1266
  }
909
 
  tmp= engine->max_keys();
 
1267
  tmp=file->max_keys();
910
1268
  if (*key_count > tmp)
911
1269
  {
912
1270
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
913
1271
    return(true);
914
1272
  }
915
1273
 
916
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
917
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
1274
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1275
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
918
1276
  if (!*key_info_buffer || ! key_part_info)
919
1277
    return(true);                               // Out of memory
920
1278
 
954
1312
    key_info->usable_key_parts= key_number;
955
1313
    key_info->algorithm= key->key_create_info.algorithm;
956
1314
 
 
1315
    /* Take block size from key part or table part */
 
1316
    /*
 
1317
      TODO: Add warning if block size changes. We can't do it here, as
 
1318
      this may depend on the size of the key
 
1319
    */
 
1320
    key_info->block_size= (key->key_create_info.block_size ?
 
1321
                           key->key_create_info.block_size :
 
1322
                           create_info->key_block_size);
 
1323
 
 
1324
    if (key_info->block_size)
 
1325
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
1326
 
957
1327
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
958
1328
                                           key->key_create_info.comment.str,
959
1329
                                           key->key_create_info.comment.str +
975
1345
      key_info->comment.str= key->key_create_info.comment.str;
976
1346
    }
977
1347
 
978
 
    message::Table::Field *protofield= NULL;
979
 
 
980
1348
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
981
1349
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
982
1350
    {
983
1351
      uint32_t length;
984
1352
      Key_part_spec *dup_column;
985
 
      int proto_field_nr= 0;
986
1353
 
987
1354
      it.rewind();
988
1355
      field=0;
989
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
1356
      while ((sql_field=it++) &&
990
1357
             my_strcasecmp(system_charset_info,
991
1358
                           column->field_name.str,
992
1359
                           sql_field->field_name))
993
 
      {
994
1360
        field++;
995
 
      }
996
 
 
997
1361
      if (!sql_field)
998
1362
      {
999
1363
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
1364
        return(true);
1001
1365
      }
1002
 
 
1003
1366
      while ((dup_column= cols2++) != column)
1004
1367
      {
1005
1368
        if (!my_strcasecmp(system_charset_info,
1006
 
                           column->field_name.str, dup_column->field_name.str))
 
1369
                           column->field_name.str, dup_column->field_name.str))
1007
1370
        {
1008
1371
          my_printf_error(ER_DUP_FIELDNAME,
1009
1372
                          ER(ER_DUP_FIELDNAME),MYF(0),
1012
1375
        }
1013
1376
      }
1014
1377
      cols2.rewind();
1015
 
 
1016
 
      if (create_proto.field_size() > 0)
1017
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1018
 
 
1019
1378
      {
1020
 
        column->length*= sql_field->charset->mbmaxlen;
1021
 
 
1022
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1023
 
        {
1024
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1025
 
          {
1026
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1027
 
            return true;
1028
 
          }
1029
 
          if (! column->length)
1030
 
          {
1031
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
1032
 
            return true;
1033
 
          }
1034
 
        }
1035
 
 
1036
 
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
 
        {
1038
 
          if (key->type == Key::PRIMARY)
1039
 
          {
1040
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1041
 
            sql_field->flags|= NOT_NULL_FLAG;
 
1379
        column->length*= sql_field->charset->mbmaxlen;
 
1380
 
 
1381
        if (f_is_blob(sql_field->pack_flag))
 
1382
        {
 
1383
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
1384
          {
 
1385
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
1386
            return(true);
 
1387
          }
 
1388
          if (!column->length)
 
1389
          {
 
1390
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
1391
            return(true);
 
1392
          }
 
1393
        }
 
1394
        if (!(sql_field->flags & NOT_NULL_FLAG))
 
1395
        {
 
1396
          if (key->type == Key::PRIMARY)
 
1397
          {
 
1398
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
1399
            sql_field->flags|= NOT_NULL_FLAG;
 
1400
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1042
1401
            null_fields--;
1043
 
 
1044
 
            if (protofield)
1045
 
            {
1046
 
              message::Table::Field::FieldConstraints *constraints;
1047
 
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
1049
 
            }
1050
 
 
1051
 
          }
1052
 
          else
 
1402
          }
 
1403
          else
1053
1404
          {
1054
1405
            key_info->flags|= HA_NULL_PART_KEY;
1055
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1406
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1056
1407
            {
1057
1408
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1058
 
              return true;
 
1409
              return(true);
1059
1410
            }
1060
1411
          }
1061
 
        }
1062
 
 
1063
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
 
        {
1065
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1066
 
            auto_increment--;                   // Field is used
1067
 
        }
 
1412
        }
 
1413
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
1414
        {
 
1415
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
 
1416
            auto_increment--;                   // Field is used
 
1417
        }
1068
1418
      }
1069
1419
 
1070
1420
      key_part_info->fieldnr= field;
1071
1421
      key_part_info->offset=  (uint16_t) sql_field->offset;
1072
 
      key_part_info->key_type= 0;
 
1422
      key_part_info->key_type=sql_field->pack_flag;
1073
1423
      length= sql_field->key_length;
1074
1424
 
1075
1425
      if (column->length)
1076
1426
      {
1077
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
1427
        if (f_is_blob(sql_field->pack_flag))
1078
1428
        {
1079
1429
          if ((length=column->length) > max_key_length ||
1080
 
              length > engine->max_key_part_length())
 
1430
              length > file->max_key_part_length())
1081
1431
          {
1082
 
            length= min(max_key_length, engine->max_key_part_length());
 
1432
            length= min(max_key_length, file->max_key_part_length());
1083
1433
            if (key->type == Key::MULTIPLE)
1084
1434
            {
1085
1435
              /* not a critical problem */
1099
1449
          }
1100
1450
        }
1101
1451
        else if ((column->length > length ||
1102
 
            ! Field::type_can_have_key_part(sql_field->sql_type)))
 
1452
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
 
1453
                   ((f_is_packed(sql_field->pack_flag) ||
 
1454
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
 
1455
                      (key_info->flags & HA_NOSAME))) &&
 
1456
                    column->length != length)))
1103
1457
        {
1104
1458
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1105
1459
          return(true);
1106
1460
        }
1107
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1108
 
        {
 
1461
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1109
1462
          length=column->length;
1110
 
        }
1111
1463
      }
1112
1464
      else if (length == 0)
1113
1465
      {
1114
1466
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1115
1467
          return(true);
1116
1468
      }
1117
 
      if (length > engine->max_key_part_length())
 
1469
      if (length > file->max_key_part_length())
1118
1470
      {
1119
 
        length= engine->max_key_part_length();
 
1471
        length= file->max_key_part_length();
1120
1472
        if (key->type == Key::MULTIPLE)
1121
1473
        {
1122
1474
          /* not a critical problem */
1137
1489
      key_part_info->length=(uint16_t) length;
1138
1490
      /* Use packed keys for long strings on the first column */
1139
1491
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1140
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1141
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1142
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1492
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1493
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1494
            sql_field->pack_flag & FIELDFLAG_BLOB)))
1143
1495
      {
1144
 
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
 
1496
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
1145
1497
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1146
 
        {
1147
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1148
 
        }
1149
 
        else
1150
 
        {
1151
 
          key_info->flags|= HA_PACK_KEY;
1152
 
        }
 
1498
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
1499
        else
 
1500
          key_info->flags|= HA_PACK_KEY;
1153
1501
      }
1154
1502
      /* Check if the key segment is partial, set the key flag accordingly */
1155
1503
      if (length != sql_field->key_length)
1184
1532
        key_info->name=(char*) key_name;
1185
1533
      }
1186
1534
    }
1187
 
 
1188
1535
    if (!key_info->name || check_column_name(key_info->name))
1189
1536
    {
1190
1537
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1538
      return(true);
1192
1539
    }
1193
 
 
1194
1540
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1541
      unique_key=1;
1197
 
    }
1198
 
 
1199
1542
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1543
    if (key_length > max_key_length)
1202
1544
    {
1203
1545
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1546
      return(true);
1205
1547
    }
1206
 
 
1207
1548
    key_info++;
1208
1549
  }
1209
 
 
1210
1550
  if (!unique_key && !primary_key &&
1211
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1551
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1212
1552
  {
1213
1553
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1554
    return(true);
1215
1555
  }
1216
 
 
1217
1556
  if (auto_increment > 0)
1218
1557
  {
1219
1558
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1220
1559
    return(true);
1221
1560
  }
1222
1561
  /* Sort keys in optimized order */
1223
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1224
 
                     (qsort_cmp) sort_keys);
 
1562
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1563
           (qsort_cmp) sort_keys);
1225
1564
 
1226
1565
  /* Check fields. */
1227
1566
  it.rewind();
1294
1633
  return 0;
1295
1634
}
1296
1635
 
1297
 
static bool locked_create_event(Session *session,
1298
 
                                const identifier::Table &identifier,
1299
 
                                HA_CREATE_INFO *create_info,
1300
 
                                message::Table &table_proto,
1301
 
                                AlterInfo *alter_info,
1302
 
                                bool is_if_not_exists,
1303
 
                                bool internal_tmp_table,
1304
 
                                uint db_options,
1305
 
                                uint key_count,
1306
 
                                KeyInfo *key_info_buffer)
1307
 
{
1308
 
  bool error= true;
1309
 
 
1310
 
  {
1311
 
 
1312
 
    /*
1313
 
      @note if we are building a temp table we need to check to see if a temp table
1314
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1315
 
      to create a table under a temporary table.
1316
 
    */
1317
 
    bool exists= 
1318
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1319
 
                                            identifier.getType() != message::Table::STANDARD );
1320
 
 
1321
 
    if (exists)
1322
 
    {
1323
 
      if (is_if_not_exists)
1324
 
      {
1325
 
        error= false;
1326
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1327
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1328
 
                            identifier.getTableName().c_str());
1329
 
        create_info->table_existed= 1;          // Mark that table existed
1330
 
        return error;
1331
 
      }
1332
 
 
1333
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1334
 
 
1335
 
      return error;
1336
 
    }
1337
 
 
1338
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1339
 
    {
1340
 
      /*
1341
 
        We don't assert here, but check the result, because the table could be
1342
 
        in the table definition cache and in the same time the .frm could be
1343
 
        missing from the disk, in case of manual intervention which deletes
1344
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1345
 
        Then she could create the table. This case is pretty obscure and
1346
 
        therefore we don't introduce a new error message only for it.
1347
 
      */
1348
 
      /*
1349
 
        @todo improve this error condition.
1350
 
      */
1351
 
      if (definition::Cache::singleton().find(identifier.getKey()))
1352
 
      {
1353
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
 
 
1355
 
        return error;
1356
 
      }
1357
 
    }
1358
 
  }
1359
 
 
1360
 
  session->set_proc_info("creating table");
1361
 
  create_info->table_existed= 0;                // Mark that table is created
1362
 
 
1363
 
  create_info->table_options= db_options;
1364
 
 
1365
 
  if (not rea_create_table(session, identifier,
1366
 
                           table_proto,
1367
 
                           create_info, alter_info->create_list,
1368
 
                           key_count, key_info_buffer))
1369
 
  {
1370
 
    return error;
1371
 
  }
1372
 
 
1373
 
  if (identifier.getType() == message::Table::TEMPORARY)
1374
 
  {
1375
 
    /* Open table and put in temporary table list */
1376
 
    if (not (session->open_temporary_table(identifier)))
1377
 
    {
1378
 
      (void) session->rm_temporary_table(identifier);
1379
 
      return error;
1380
 
    }
1381
 
  }
1382
 
 
1383
 
  /* 
1384
 
    We keep this behind the lock to make sure ordering is correct for a table.
1385
 
    This is a very unlikely problem where before we would write out to the
1386
 
    trans log, someone would do a delete/create operation.
1387
 
  */
1388
 
 
1389
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1390
 
  {
1391
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1392
 
    transaction_services.createTable(*session, table_proto);
1393
 
  }
1394
 
 
1395
 
  return false;
1396
 
}
1397
 
 
1398
1636
 
1399
1637
/*
1400
1638
  Ignore the name of this function... it locks :(
1402
1640
  Create a table
1403
1641
 
1404
1642
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1643
    mysql_create_table_no_lock()
1406
1644
    session                     Thread object
1407
1645
    db                  Database
1408
1646
    table_name          Table name
1418
1656
 
1419
1657
    Note that this function assumes that caller already have taken
1420
1658
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1659
    that concurrent operations won't intervene. mysql_create_table()
1422
1660
    is a wrapper that can be used for this.
1423
1661
 
1424
1662
  RETURN VALUES
1426
1664
    true  error
1427
1665
*/
1428
1666
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1667
bool mysql_create_table_no_lock(Session *session,
 
1668
                                const char *db, const char *table_name,
1431
1669
                                HA_CREATE_INFO *create_info,
1432
 
                                message::Table &table_proto,
 
1670
                                message::Table *table_proto,
1433
1671
                                AlterInfo *alter_info,
1434
1672
                                bool internal_tmp_table,
1435
 
                                uint32_t select_field_count,
1436
 
                                bool is_if_not_exists)
 
1673
                                uint32_t select_field_count)
1437
1674
{
 
1675
  char          path[FN_REFLEN];
 
1676
  uint32_t          path_length;
1438
1677
  uint          db_options, key_count;
1439
 
  KeyInfo               *key_info_buffer;
 
1678
  KEY           *key_info_buffer;
 
1679
  handler       *file;
1440
1680
  bool          error= true;
1441
 
 
1442
1681
  /* Check for duplicate fields and check type of table to create */
1443
 
  if (not alter_info->create_list.elements)
 
1682
  if (!alter_info->create_list.elements)
1444
1683
  {
1445
1684
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1446
1685
               MYF(0));
1447
1686
    return true;
1448
1687
  }
1449
 
  assert(identifier.getTableName() == table_proto.name());
 
1688
  assert(strcmp(table_name,table_proto->name().c_str())==0);
 
1689
  if (check_engine(session, table_name, create_info))
 
1690
    return true;
1450
1691
  db_options= create_info->table_options;
1451
 
 
1452
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1453
 
 
1454
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1455
 
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1456
 
                               internal_tmp_table,
1457
 
                               &db_options,
1458
 
                               &key_info_buffer, &key_count,
1459
 
                               select_field_count))
1460
 
  {
1461
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
 
    error= locked_create_event(session,
1463
 
                               identifier,
1464
 
                               create_info,
1465
 
                               table_proto,
1466
 
                               alter_info,
1467
 
                               is_if_not_exists,
1468
 
                               internal_tmp_table,
1469
 
                               db_options, key_count,
1470
 
                               key_info_buffer);
1471
 
  }
1472
 
 
 
1692
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1693
    db_options|=HA_OPTION_PACK_RECORD;
 
1694
  if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
 
1695
                              create_info->db_type)))
 
1696
  {
 
1697
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
1698
    return true;
 
1699
  }
 
1700
 
 
1701
  set_table_default_charset(create_info, (char*) db);
 
1702
 
 
1703
  if (mysql_prepare_create_table(session, create_info, alter_info,
 
1704
                                 internal_tmp_table,
 
1705
                                 &db_options, file,
 
1706
                                 &key_info_buffer, &key_count,
 
1707
                                 select_field_count))
 
1708
    goto err;
 
1709
 
 
1710
      /* Check if table exists */
 
1711
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1712
  {
 
1713
    path_length= build_tmptable_filename(session, path, sizeof(path));
 
1714
  }
 
1715
  else
 
1716
  {
 
1717
 #ifdef FN_DEVCHAR
 
1718
    /* check if the table name contains FN_DEVCHAR when defined */
 
1719
    if (strchr(table_name, FN_DEVCHAR))
 
1720
    {
 
1721
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
 
1722
      return true;
 
1723
    }
 
1724
#endif
 
1725
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
 
1726
  }
 
1727
 
 
1728
  /* Check if table already exists */
 
1729
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1730
      session->find_temporary_table(db, table_name))
 
1731
  {
 
1732
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1733
    {
 
1734
      create_info->table_existed= 1;            // Mark that table existed
 
1735
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1736
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1737
                          table_name);
 
1738
      error= 0;
 
1739
      goto err;
 
1740
    }
 
1741
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1742
    goto err;
 
1743
  }
 
1744
 
 
1745
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1746
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1747
  {
 
1748
    plugin::Registry &plugins= plugin::Registry::singleton();
 
1749
    if (plugins.storage_engine.getTableProto(path, NULL)==EEXIST)
 
1750
    {
 
1751
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1752
      {
 
1753
        error= false;
 
1754
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1755
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1756
                            table_name);
 
1757
        create_info->table_existed= 1;          // Mark that table existed
 
1758
      }
 
1759
      else 
 
1760
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1761
 
 
1762
      goto unlock_and_end;
 
1763
    }
 
1764
    /*
 
1765
      We don't assert here, but check the result, because the table could be
 
1766
      in the table definition cache and in the same time the .frm could be
 
1767
      missing from the disk, in case of manual intervention which deletes
 
1768
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1769
      Then she could create the table. This case is pretty obscure and
 
1770
      therefore we don't introduce a new error message only for it.
 
1771
    */
 
1772
    if (TableShare::getShare(db, table_name))
 
1773
    {
 
1774
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1775
      goto unlock_and_end;
 
1776
    }
 
1777
  }
 
1778
 
 
1779
  /*
 
1780
    Check that table with given name does not already
 
1781
    exist in any storage engine. In such a case it should
 
1782
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1783
    unless user specified CREATE TABLE IF EXISTS
 
1784
    The LOCK_open mutex has been locked to make sure no
 
1785
    one else is attempting to discover the table. Since
 
1786
    it's not on disk as a frm file, no one could be using it!
 
1787
  */
 
1788
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1789
  {
 
1790
    bool create_if_not_exists =
 
1791
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1792
 
 
1793
    char table_path[FN_REFLEN];
 
1794
    uint32_t          table_path_length;
 
1795
 
 
1796
    table_path_length= build_table_filename(table_path, sizeof(table_path),
 
1797
                                            db, table_name, false);
 
1798
 
 
1799
    plugin::Registry &plugins= plugin::Registry::singleton();
 
1800
    int retcode= plugins.storage_engine.getTableProto(table_path, NULL);
 
1801
    switch (retcode)
 
1802
    {
 
1803
      case ENOENT:
 
1804
        /* Normal case, no table exists. we can go and create it */
 
1805
        break;
 
1806
      case EEXIST:
 
1807
        if (create_if_not_exists)
 
1808
        {
 
1809
          error= false;
 
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;                // Mark that table existed
 
1814
          goto unlock_and_end;
 
1815
        }
 
1816
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1817
        goto unlock_and_end;
 
1818
      default:
 
1819
        my_error(retcode, MYF(0),table_name);
 
1820
        goto unlock_and_end;
 
1821
    }
 
1822
  }
 
1823
 
 
1824
  session->set_proc_info("creating table");
 
1825
  create_info->table_existed= 0;                // Mark that table is created
 
1826
 
 
1827
  create_info->table_options=db_options;
 
1828
 
 
1829
  if (rea_create_table(session, path, db, table_name,
 
1830
                       table_proto,
 
1831
                       create_info, alter_info->create_list,
 
1832
                       key_count, key_info_buffer))
 
1833
    goto unlock_and_end;
 
1834
 
 
1835
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1836
  {
 
1837
    /* Open table and put in temporary table list */
 
1838
    if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
 
1839
    {
 
1840
      (void) session->rm_temporary_table(create_info->db_type, path);
 
1841
      goto unlock_and_end;
 
1842
    }
 
1843
  }
 
1844
 
 
1845
  /*
 
1846
    Don't write statement if:
 
1847
    - It is an internal temporary table,
 
1848
    - Row-based logging is used and it we are creating a temporary table, or
 
1849
    - The binary log is not open.
 
1850
    Otherwise, the statement shall be binlogged.
 
1851
   */
 
1852
  if (!internal_tmp_table &&
 
1853
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1854
    write_bin_log(session, true, session->query, session->query_length);
 
1855
  error= false;
 
1856
unlock_and_end:
 
1857
  pthread_mutex_unlock(&LOCK_open);
 
1858
 
 
1859
err:
1473
1860
  session->set_proc_info("After create");
1474
 
 
 
1861
  delete file;
1475
1862
  return(error);
1476
1863
}
1477
1864
 
1478
 
/**
1479
 
  @note the following two methods implement create [temporary] table.
 
1865
 
 
1866
/*
 
1867
  Database locking aware wrapper for mysql_create_table_no_lock(),
1480
1868
*/
1481
 
static bool drizzle_create_table(Session *session,
1482
 
                                 const identifier::Table &identifier,
1483
 
                                 HA_CREATE_INFO *create_info,
1484
 
                                 message::Table &table_proto,
1485
 
                                 AlterInfo *alter_info,
1486
 
                                 bool internal_tmp_table,
1487
 
                                 uint32_t select_field_count,
1488
 
                                 bool is_if_not_exists)
 
1869
 
 
1870
bool mysql_create_table(Session *session, const char *db, const char *table_name,
 
1871
                        HA_CREATE_INFO *create_info,
 
1872
                        message::Table *table_proto,
 
1873
                        AlterInfo *alter_info,
 
1874
                        bool internal_tmp_table,
 
1875
                        uint32_t select_field_count)
1489
1876
{
1490
1877
  Table *name_lock= NULL;
1491
1878
  bool result;
1492
1879
 
1493
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1494
 
  {
1495
 
    result= true;
1496
 
  }
1497
 
  else if (name_lock == NULL)
1498
 
  {
1499
 
    if (is_if_not_exists)
1500
 
    {
1501
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
 
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1503
 
                          identifier.getTableName().c_str());
1504
 
      create_info->table_existed= 1;
1505
 
      result= false;
1506
 
    }
1507
 
    else
1508
 
    {
1509
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1880
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1881
  {
 
1882
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
1883
    {
1510
1884
      result= true;
1511
 
    }
1512
 
  }
1513
 
  else
1514
 
  {
1515
 
    result= create_table_no_lock(session,
1516
 
                                       identifier,
1517
 
                                       create_info,
1518
 
                                       table_proto,
1519
 
                                       alter_info,
1520
 
                                       internal_tmp_table,
1521
 
                                       select_field_count,
1522
 
                                       is_if_not_exists);
1523
 
  }
1524
 
 
 
1885
      goto unlock;
 
1886
    }
 
1887
    if (name_lock == NULL)
 
1888
    {
 
1889
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1890
      {
 
1891
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1892
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1893
                            table_name);
 
1894
        create_info->table_existed= 1;
 
1895
        result= false;
 
1896
      }
 
1897
      else
 
1898
      {
 
1899
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1900
        result= true;
 
1901
      }
 
1902
      goto unlock;
 
1903
    }
 
1904
  }
 
1905
 
 
1906
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1907
                                     table_proto,
 
1908
                                     alter_info,
 
1909
                                     internal_tmp_table,
 
1910
                                     select_field_count);
 
1911
 
 
1912
unlock:
1525
1913
  if (name_lock)
1526
1914
  {
1527
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1915
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1528
1916
    session->unlink_open_table(name_lock);
 
1917
    pthread_mutex_unlock(&LOCK_open);
1529
1918
  }
1530
1919
 
1531
1920
  return(result);
1533
1922
 
1534
1923
 
1535
1924
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
1537
 
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
1540
 
                        HA_CREATE_INFO *create_info,
1541
 
                        message::Table &table_proto,
1542
 
                        AlterInfo *alter_info,
1543
 
                        bool internal_tmp_table,
1544
 
                        uint32_t select_field_count,
1545
 
                        bool is_if_not_exists)
1546
 
{
1547
 
  if (identifier.isTmp())
1548
 
  {
1549
 
    return create_table_no_lock(session,
1550
 
                                      identifier,
1551
 
                                      create_info,
1552
 
                                      table_proto,
1553
 
                                      alter_info,
1554
 
                                      internal_tmp_table,
1555
 
                                      select_field_count,
1556
 
                                      is_if_not_exists);
1557
 
  }
1558
 
 
1559
 
  return drizzle_create_table(session,
1560
 
                              identifier,
1561
 
                              create_info,
1562
 
                              table_proto,
1563
 
                              alter_info,
1564
 
                              internal_tmp_table,
1565
 
                              select_field_count,
1566
 
                              is_if_not_exists);
1567
 
}
1568
 
 
1569
 
 
1570
 
/*
1571
1925
** Give the key name after the first field with an optional '_#' after
1572
1926
**/
1573
1927
 
1574
1928
static bool
1575
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1929
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1576
1930
{
1577
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1931
  for (KEY *key=start ; key != end ; key++)
1578
1932
    if (!my_strcasecmp(system_charset_info,name,key->name))
1579
1933
      return 1;
1580
1934
  return 0;
1582
1936
 
1583
1937
 
1584
1938
static char *
1585
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1939
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1586
1940
{
1587
1941
  char buff[MAX_FIELD_NAME],*buff_end;
1588
1942
 
1600
1954
  for (uint32_t i=2 ; i< 100; i++)
1601
1955
  {
1602
1956
    *buff_end= '_';
1603
 
    internal::int10_to_str(i, buff_end+1, 10);
 
1957
    int10_to_str(i, buff_end+1, 10);
1604
1958
    if (!check_if_keyname_exists(buff,start,end))
1605
 
      return memory::sql_strdup(buff);
 
1959
      return sql_strdup(buff);
1606
1960
  }
1607
1961
  return (char*) "not_specified";               // Should never happen
1608
1962
}
1616
1970
  Rename a table.
1617
1971
 
1618
1972
  SYNOPSIS
1619
 
    rename_table()
1620
 
      session
 
1973
    mysql_rename_table()
1621
1974
      base                      The plugin::StorageEngine handle.
1622
1975
      old_db                    The old database name.
1623
1976
      old_name                  The old table name.
1624
1977
      new_db                    The new database name.
1625
1978
      new_name                  The new table name.
 
1979
      flags                     flags for build_table_filename().
 
1980
                                FN_FROM_IS_TMP old_name is temporary.
 
1981
                                FN_TO_IS_TMP   new_name is temporary.
 
1982
                                NO_FRM_RENAME  Don't rename the FRM file
 
1983
                                but only the table in the storage engine.
1626
1984
 
1627
1985
  RETURN
1628
1986
    false   OK
1630
1988
*/
1631
1989
 
1632
1990
bool
1633
 
rename_table(Session &session,
1634
 
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1991
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
 
1992
                   const char *old_name, const char *new_db,
 
1993
                   const char *new_name, uint32_t flags)
1637
1994
{
 
1995
  Session *session= current_session;
 
1996
  char from[FN_REFLEN], to[FN_REFLEN];
 
1997
  char *from_base= from, *to_base= to;
1638
1998
  int error= 0;
1639
1999
 
1640
2000
  assert(base);
1641
2001
 
1642
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
2002
  build_table_filename(from, sizeof(from), old_db, old_name,
 
2003
                       flags & FN_FROM_IS_TMP);
 
2004
  build_table_filename(to, sizeof(to), new_db, new_name,
 
2005
                       flags & FN_TO_IS_TMP);
 
2006
 
 
2007
  if (!(error=base->renameTable(session, from_base, to_base)))
1643
2008
  {
1644
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1645
 
    return true;
 
2009
    if(!(flags & NO_FRM_RENAME)
 
2010
       && base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
2011
       && rename_table_proto_file(from_base, to_base))
 
2012
    {
 
2013
      error= my_errno;
 
2014
      base->renameTable(session, to_base, from_base);
 
2015
    }
1646
2016
  }
1647
2017
 
1648
 
  error= base->renameTable(session, from, to);
1649
 
 
1650
2018
  if (error == HA_ERR_WRONG_COMMAND)
1651
 
  {
1652
2019
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1653
 
  }
1654
2020
  else if (error)
1655
 
  {
1656
 
    std::string from_path;
1657
 
    std::string to_path;
1658
 
 
1659
 
    from.getSQLPath(from_path);
1660
 
    to.getSQLPath(to_path);
1661
 
 
1662
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1663
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1664
 
 
1665
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1666
 
  }
1667
 
 
1668
 
  return error ? true : false; 
 
2021
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
2022
  return(error != 0);
1669
2023
}
1670
2024
 
1671
2025
 
1674
2028
 
1675
2029
  SYNOPSIS
1676
2030
    wait_while_table_is_used()
1677
 
    session                     Thread Cursor
 
2031
    session                     Thread handler
1678
2032
    table               Table to remove from cache
1679
2033
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1680
2034
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1684
2038
   the table is closed.
1685
2039
 
1686
2040
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
2041
    Lock on LOCK_open
1688
2042
    Win32 clients must also have a WRITE LOCK on the table !
1689
2043
*/
1690
2044
 
1692
2046
                              enum ha_extra_function function)
1693
2047
{
1694
2048
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
2049
  safe_mutex_assert_owner(&LOCK_open);
1696
2050
 
1697
 
  table->cursor->extra(function);
 
2051
  table->file->extra(function);
1698
2052
  /* Mark all tables that are in use as 'old' */
1699
 
  session->abortLock(table);    /* end threads waiting on lock */
 
2053
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1700
2054
 
1701
2055
  /* Wait until all there are no other threads that has this table open */
1702
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1703
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
2056
  remove_table_from_cache(session, table->s->db.str,
 
2057
                          table->s->table_name.str,
 
2058
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1704
2059
}
1705
2060
 
1706
2061
/*
1708
2063
 
1709
2064
  SYNOPSIS
1710
2065
    close_cached_table()
1711
 
    session                     Thread Cursor
 
2066
    session                     Thread handler
1712
2067
    table               Table to remove from cache
1713
2068
 
1714
2069
  NOTES
1716
2071
    reopen the table.
1717
2072
 
1718
2073
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
2074
    Lock on LOCK_open
1720
2075
    Win32 clients must also have a WRITE LOCK on the table !
1721
2076
*/
1722
2077
 
1727
2082
  /* Close lock if this is not got with LOCK TABLES */
1728
2083
  if (lock)
1729
2084
  {
1730
 
    unlockTables(lock);
 
2085
    mysql_unlock_tables(this, lock);
1731
2086
    lock= NULL;                 // Start locked threads
1732
2087
  }
1733
2088
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
2089
  unlink_open_table(table);
1735
2090
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1737
 
  locking::broadcast_refresh();
 
2091
  /* When lock on LOCK_open is freed other threads can continue */
 
2092
  broadcast_refresh();
1738
2093
}
1739
2094
 
1740
2095
/*
1743
2098
    true  Message should be sent by caller
1744
2099
          (admin operation or network communication failed)
1745
2100
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
2101
static bool mysql_admin_table(Session* session, TableList* tables,
1747
2102
                              HA_CHECK_OPT* check_opt,
1748
2103
                              const char *operator_name,
1749
2104
                              thr_lock_type lock_type,
1750
2105
                              bool open_for_modify,
1751
 
                              int (Cursor::*operator_func)(Session *,
 
2106
                              bool no_warnings_for_error,
 
2107
                              uint32_t extra_open_options,
 
2108
                              int (*prepare_func)(Session *, TableList *,
 
2109
                                                  HA_CHECK_OPT *),
 
2110
                              int (handler::*operator_func)(Session *,
1752
2111
                                                            HA_CHECK_OPT *))
1753
2112
{
1754
2113
  TableList *table;
1757
2116
  Item *item;
1758
2117
  LEX *lex= session->lex;
1759
2118
  int result_code= 0;
1760
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1761
2119
  const CHARSET_INFO * const cs= system_charset_info;
1762
2120
 
1763
2121
  if (! session->endActiveTransaction())
1772
2130
  item->maybe_null = 1;
1773
2131
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
2132
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
2133
  if (session->client->sendFields(&field_list))
1776
2134
    return true;
1777
2135
 
1778
2136
  for (table= tables; table; table= table->next_local)
1779
2137
  {
1780
2138
    char table_name[NAME_LEN*2+2];
 
2139
    char* db = table->db;
1781
2140
    bool fatal_error=0;
1782
2141
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
2142
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2143
    session->open_options|= extra_open_options;
1784
2144
    table->lock_type= lock_type;
1785
2145
    /* open only one table from local list of command */
1786
2146
    {
1793
2153
      /*
1794
2154
        Time zone tables and SP tables can be add to lex->query_tables list,
1795
2155
        so it have to be prepared.
1796
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2156
        TODO: Investigate if we can put extra tables into argument instead of
 
2157
        using lex->query_tables
1797
2158
      */
1798
2159
      lex->query_tables= table;
1799
2160
      lex->query_tables_last= &table->next_global;
1800
2161
      lex->query_tables_own_last= 0;
1801
 
      session->no_warnings_for_error= 0;
 
2162
      session->no_warnings_for_error= no_warnings_for_error;
1802
2163
 
1803
2164
      session->openTablesLock(table);
1804
2165
      session->no_warnings_for_error= 0;
1805
2166
      table->next_global= save_next_global;
1806
2167
      table->next_local= save_next_local;
 
2168
      session->open_options&= ~extra_open_options;
 
2169
    }
 
2170
 
 
2171
    if (prepare_func)
 
2172
    {
 
2173
      switch ((*prepare_func)(session, table, check_opt)) {
 
2174
      case  1:           // error, message written to net
 
2175
        ha_autocommit_or_rollback(session, 1);
 
2176
        session->endTransaction(ROLLBACK);
 
2177
        session->close_thread_tables();
 
2178
        continue;
 
2179
      case -1:           // error, message could be written to net
 
2180
        goto err;
 
2181
      default:           // should be 0 otherwise
 
2182
        ;
 
2183
      }
1807
2184
    }
1808
2185
 
1809
2186
    /*
1827
2204
    {
1828
2205
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
2206
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
2207
      session->client->store(table_name);
 
2208
      session->client->store(operator_name);
 
2209
      session->client->store(STRING_WITH_LEN("error"));
1833
2210
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
2211
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
2212
      session->client->store(buff, length);
 
2213
      ha_autocommit_or_rollback(session, 0);
1837
2214
      session->endTransaction(COMMIT);
1838
2215
      session->close_thread_tables();
1839
2216
      lex->reset_query_tables_list(false);
1840
2217
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
2218
      if (session->client->flush())
1842
2219
        goto err;
1843
2220
      continue;
1844
2221
    }
1845
2222
 
1846
2223
    /* Close all instances of the table to allow repair to rename files */
1847
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2224
    if (lock_type == TL_WRITE && table->table->s->version)
1848
2225
    {
1849
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1850
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1851
 
                                                  "Waiting to get writelock");
1852
 
      session->abortLock(table->table);
1853
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
2226
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2227
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
2228
                                              "Waiting to get writelock");
 
2229
      mysql_lock_abort(session,table->table);
 
2230
      remove_table_from_cache(session, table->table->s->db.str,
 
2231
                              table->table->s->table_name.str,
 
2232
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2233
                              RTFC_CHECK_KILLED_FLAG);
1855
2234
      session->exit_cond(old_message);
1856
 
      if (session->getKilled())
 
2235
      if (session->killed)
1857
2236
        goto err;
1858
2237
      open_for_modify= 0;
1859
2238
    }
1860
2239
 
1861
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
2240
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2241
    {
 
2242
      session->client->store(table_name);
 
2243
      session->client->store(operator_name);
 
2244
      session->client->store(STRING_WITH_LEN("warning"));
 
2245
      session->client->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2246
      if (session->client->flush())
 
2247
        goto err;
 
2248
    }
 
2249
 
 
2250
    result_code = (table->table->file->*operator_func)(session, check_opt);
1862
2251
 
1863
2252
send_result:
1864
2253
 
1869
2258
      DRIZZLE_ERROR *err;
1870
2259
      while ((err= it++))
1871
2260
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
2261
        session->client->store(table_name);
 
2262
        session->client->store(operator_name);
 
2263
        session->client->store(warning_level_names[err->level].str,
1875
2264
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
2265
        session->client->store(err->msg);
 
2266
        if (session->client->flush())
1878
2267
          goto err;
1879
2268
      }
1880
2269
      drizzle_reset_errors(session, true);
1881
2270
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
2271
    session->client->store(table_name);
 
2272
    session->client->store(operator_name);
 
2273
 
 
2274
send_result_message:
1884
2275
 
1885
2276
    switch (result_code) {
1886
2277
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
2279
        char buf[ERRMSGSIZE+20];
1889
2280
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
2281
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
2282
        session->client->store(STRING_WITH_LEN("note"));
 
2283
        session->client->store(buf, length);
1893
2284
      }
1894
2285
      break;
1895
2286
 
1896
2287
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
2288
      session->client->store(STRING_WITH_LEN("status"));
 
2289
      session->client->store(STRING_WITH_LEN("OK"));
1899
2290
      break;
1900
2291
 
1901
2292
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
2293
      session->client->store(STRING_WITH_LEN("status"));
 
2294
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
2295
      break;
1905
2296
 
1906
2297
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
2298
      session->client->store(STRING_WITH_LEN("status"));
 
2299
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
2300
      open_for_modify= false;
1910
2301
      break;
1911
2302
 
1912
2303
    case HA_ADMIN_ALREADY_DONE:
1913
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1914
 
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
 
2304
      session->client->store(STRING_WITH_LEN("status"));
 
2305
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
2306
      break;
1916
2307
 
1917
2308
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
2309
      session->client->store(STRING_WITH_LEN("error"));
 
2310
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
2311
      fatal_error=1;
1921
2312
      break;
1922
2313
 
1923
2314
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1926
 
      break;
 
2315
      session->client->store(STRING_WITH_LEN("error"));
 
2316
      session->client->store(STRING_WITH_LEN("Invalid argument"));
 
2317
      break;
 
2318
 
 
2319
    case HA_ADMIN_TRY_ALTER:
 
2320
    {
 
2321
      /*
 
2322
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2323
        "try with alter", so here we close the table, do an ALTER Table,
 
2324
        reopen the table and do ha_innobase::analyze() on it.
 
2325
      */
 
2326
      ha_autocommit_or_rollback(session, 0);
 
2327
      session->close_thread_tables();
 
2328
      TableList *save_next_local= table->next_local,
 
2329
                 *save_next_global= table->next_global;
 
2330
      table->next_local= table->next_global= 0;
 
2331
      result_code= mysql_recreate_table(session, table);
 
2332
      /*
 
2333
        mysql_recreate_table() can push OK or ERROR.
 
2334
        Clear 'OK' status. If there is an error, keep it:
 
2335
        we will store the error message in a result set row
 
2336
        and then clear.
 
2337
      */
 
2338
      if (session->main_da.is_ok())
 
2339
        session->main_da.reset_diagnostics_area();
 
2340
      ha_autocommit_or_rollback(session, 0);
 
2341
      session->close_thread_tables();
 
2342
      if (!result_code) // recreation went ok
 
2343
      {
 
2344
        if ((table->table= session->openTableLock(table, lock_type)) &&
 
2345
            ((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
 
2346
          result_code= 0; // analyze went ok
 
2347
      }
 
2348
      if (result_code) // either mysql_recreate_table or analyze failed
 
2349
      {
 
2350
        assert(session->is_error());
 
2351
        if (session->is_error())
 
2352
        {
 
2353
          const char *err_msg= session->main_da.message();
 
2354
          /* Hijack the row already in-progress. */
 
2355
          session->client->store(STRING_WITH_LEN("error"));
 
2356
          session->client->store(err_msg);
 
2357
          (void)session->client->flush();
 
2358
          /* Start off another row for HA_ADMIN_FAILED */
 
2359
          session->client->store(table_name);
 
2360
          session->client->store(operator_name);
 
2361
          session->clear_error();
 
2362
        }
 
2363
      }
 
2364
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2365
      table->next_local= save_next_local;
 
2366
      table->next_global= save_next_global;
 
2367
      goto send_result_message;
 
2368
    }
 
2369
    case HA_ADMIN_NEEDS_UPGRADE:
 
2370
    case HA_ADMIN_NEEDS_ALTER:
 
2371
    {
 
2372
      char buf[ERRMSGSIZE];
 
2373
      uint32_t length;
 
2374
 
 
2375
      session->client->store(STRING_WITH_LEN("error"));
 
2376
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2377
      session->client->store(buf, length);
 
2378
      fatal_error=1;
 
2379
      break;
 
2380
    }
1927
2381
 
1928
2382
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1929
2383
      {
1931
2385
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
2386
                             _("Unknown - internal error %d during operation"),
1933
2387
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
2388
        session->client->store(STRING_WITH_LEN("error"));
 
2389
        session->client->store(buf, length);
1936
2390
        fatal_error=1;
1937
2391
        break;
1938
2392
      }
1940
2394
    if (table->table)
1941
2395
    {
1942
2396
      if (fatal_error)
1943
 
      {
1944
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1945
 
      }
 
2397
        table->table->s->version=0;               // Force close of table
1946
2398
      else if (open_for_modify)
1947
2399
      {
1948
 
        if (table->table->getShare()->getType())
1949
 
        {
1950
 
          table->table->cursor->info(HA_STATUS_CONST);
1951
 
        }
 
2400
        if (table->table->s->tmp_table)
 
2401
          table->table->file->info(HA_STATUS_CONST);
1952
2402
        else
1953
2403
        {
1954
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1955
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1956
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
2404
          pthread_mutex_lock(&LOCK_open);
 
2405
          remove_table_from_cache(session, table->table->s->db.str,
 
2406
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2407
          pthread_mutex_unlock(&LOCK_open);
1957
2408
        }
1958
2409
      }
1959
2410
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
2411
    ha_autocommit_or_rollback(session, 0);
1961
2412
    session->endTransaction(COMMIT);
1962
2413
    session->close_thread_tables();
1963
2414
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
2415
    if (session->client->flush())
1965
2416
      goto err;
1966
2417
  }
1967
2418
 
1969
2420
  return(false);
1970
2421
 
1971
2422
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
2423
  ha_autocommit_or_rollback(session, 1);
1973
2424
  session->endTransaction(ROLLBACK);
1974
2425
  session->close_thread_tables();                       // Shouldn't be needed
1975
2426
  if (table)
1977
2428
  return(true);
1978
2429
}
1979
2430
 
1980
 
  /*
1981
 
    Create a new table by copying from source table
1982
 
 
1983
 
    Altough exclusive name-lock on target table protects us from concurrent
1984
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
 
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1987
 
    disregard name-locks, like I_S implementation, for example. This is a
1988
 
    temporary and should not be copied. Instead we should fix our code to
1989
 
    always honor name-locks.
1990
 
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1992
 
    during the call to plugin::StorageEngine::createTable().
1993
 
    See bug #28614 for more info.
1994
 
  */
1995
 
static bool create_table_wrapper(Session &session,
1996
 
                                 const message::Table& create_table_proto,
1997
 
                                 identifier::Table::const_reference destination_identifier,
1998
 
                                 identifier::Table::const_reference source_identifier,
1999
 
                                 bool is_engine_set)
 
2431
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2000
2432
{
2001
 
  // We require an additional table message because during parsing we used
2002
 
  // a "new" message and it will not have all of the information that the
2003
 
  // source table message would have.
2004
 
  message::Table new_table_message;
2005
 
  drizzled::error_t error;
2006
 
 
2007
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2008
 
 
2009
 
  if (not source_table_message)
2010
 
  {
2011
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  new_table_message.CopyFrom(*source_table_message);
2016
 
 
2017
 
  if (destination_identifier.isTmp())
2018
 
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
2020
 
  }
2021
 
  else
2022
 
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
2024
 
  }
2025
 
 
2026
 
  if (is_engine_set)
2027
 
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2029
 
  }
2030
 
 
2031
 
  { // We now do a selective copy of elements on to the new table.
2032
 
    new_table_message.set_name(create_table_proto.name());
2033
 
    new_table_message.set_schema(create_table_proto.schema());
2034
 
    new_table_message.set_catalog(create_table_proto.catalog());
2035
 
  }
2036
 
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2039
 
  {
2040
 
    if (new_table_message.fk_constraint(j).has_name())
2041
 
    {
2042
 
      std::string name(new_table_message.name());
2043
 
      char number[20];
2044
 
 
2045
 
      name.append("_ibfk_");
2046
 
      snprintf(number, sizeof(number), "%d", j+1);
2047
 
      name.append(number);
2048
 
 
2049
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
 
      pfkey->set_name(name);
2051
 
    }
2052
 
  }
2053
 
 
2054
 
  /*
2055
 
    As mysql_truncate don't work on a new table at this stage of
2056
 
    creation, instead create the table directly (for both normal and temporary tables).
2057
 
  */
2058
 
  bool success= plugin::StorageEngine::createTable(session,
2059
 
                                                   destination_identifier,
2060
 
                                                   new_table_message);
2061
 
 
2062
 
  if (success && not destination_identifier.isTmp())
2063
 
  {
2064
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2065
 
    transaction_services.createTable(session, new_table_message);
2066
 
  }
2067
 
 
2068
 
  return success;
 
2433
  return(mysql_admin_table(session, tables, check_opt,
 
2434
                           "optimize", TL_WRITE, 1,0,0,0,
 
2435
                           &handler::ha_optimize));
2069
2436
}
2070
2437
 
2071
2438
/*
2072
2439
  Create a table identical to the specified table
2073
2440
 
2074
2441
  SYNOPSIS
2075
 
    create_like_table()
 
2442
    mysql_create_like_table()
2076
2443
    session             Thread object
2077
2444
    table       Table list element for target table
2078
2445
    src_table   Table list element for source table
2083
2450
    true  error
2084
2451
*/
2085
2452
 
2086
 
bool create_like_table(Session* session,
2087
 
                       identifier::Table::const_reference destination_identifier,
2088
 
                       identifier::Table::const_reference source_identifier,
2089
 
                       message::Table &create_table_proto,
2090
 
                       bool is_if_not_exists,
2091
 
                       bool is_engine_set)
 
2453
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2454
                             HA_CREATE_INFO *create_info)
2092
2455
{
 
2456
  Table *name_lock= 0;
 
2457
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2458
  uint32_t dst_path_length;
 
2459
  char *db= table->db;
 
2460
  char *table_name= table->table_name;
 
2461
  int  err;
2093
2462
  bool res= true;
2094
 
  bool table_exists= false;
 
2463
  uint32_t not_used;
 
2464
  message::Table src_proto;
 
2465
 
 
2466
  plugin::Registry &plugins= plugin::Registry::singleton();
 
2467
 
 
2468
  /*
 
2469
    By opening source table we guarantee that it exists and no concurrent
 
2470
    DDL operation will mess with it. Later we also take an exclusive
 
2471
    name-lock on target table name, which makes copying of .frm file,
 
2472
    call to ha_create_table() and binlogging atomic against concurrent DML
 
2473
    and DDL operations on target table. Thus by holding both these "locks"
 
2474
    we ensure that our statement is properly isolated from all concurrent
 
2475
    operations which matter.
 
2476
  */
 
2477
  if (session->open_tables_from_list(&src_table, &not_used))
 
2478
    return true;
 
2479
 
 
2480
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2095
2481
 
2096
2482
  /*
2097
2483
    Check that destination tables does not exist. Note that its name
2098
2484
    was already checked when it was added to the table list.
2099
 
 
2100
 
    For temporary tables we don't aim to grab locks.
2101
 
  */
2102
 
  if (destination_identifier.isTmp())
2103
 
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
 
2485
  */
 
2486
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2487
  {
 
2488
    if (session->find_temporary_table(db, table_name))
 
2489
      goto table_exists;
 
2490
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
 
2491
  }
 
2492
  else
 
2493
  {
 
2494
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
2495
      goto err;
 
2496
    if (!name_lock)
 
2497
      goto table_exists;
 
2498
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2499
                                          db, table_name, false);
 
2500
    if (plugins.storage_engine.getTableProto(dst_path, NULL) == EEXIST)
 
2501
      goto table_exists;
 
2502
  }
 
2503
 
 
2504
  /*
 
2505
    Create a new table by copying from source table
 
2506
 
 
2507
    Altough exclusive name-lock on target table protects us from concurrent
 
2508
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2509
    to ha_create_table() in critical section protected by LOCK_open in order
 
2510
    to provide minimal atomicity against operations which disregard name-locks,
 
2511
    like I_S implementation, for example. This is a temporary and should not
 
2512
    be copied. Instead we should fix our code to always honor name-locks.
 
2513
 
 
2514
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2515
    during the call to ha_create_table(). See bug #28614 for more info.
 
2516
  */
 
2517
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2518
 
 
2519
  {
 
2520
    int protoerr= EEXIST;
 
2521
 
 
2522
    if (src_table->schema_table)
2105
2523
    {
2106
 
      table_exists= true;
 
2524
      if (mysql_create_like_schema_frm(session, src_table, create_info,
 
2525
                                     &src_proto))
 
2526
      {
 
2527
        pthread_mutex_unlock(&LOCK_open);
 
2528
        goto err;
 
2529
      }
2107
2530
    }
2108
2531
    else
2109
2532
    {
2110
 
      bool was_created= create_table_wrapper(*session,
2111
 
                                             create_table_proto,
2112
 
                                             destination_identifier,
2113
 
                                             source_identifier,
2114
 
                                             is_engine_set);
2115
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2116
 
      {
2117
 
        (void) session->rm_temporary_table(destination_identifier, true);
2118
 
      }
2119
 
      else if (not session->open_temporary_table(destination_identifier))
2120
 
      {
2121
 
        // We created, but we can't open... also, a hack.
2122
 
        (void) session->rm_temporary_table(destination_identifier, true);
2123
 
      }
2124
 
      else
2125
 
      {
2126
 
        res= false;
2127
 
      }
2128
 
    }
2129
 
  }
2130
 
  else // Standard table which will require locks.
2131
 
  {
2132
 
    Table *name_lock= 0;
2133
 
 
2134
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2135
 
    {
2136
 
      if (name_lock)
2137
 
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
 
        session->unlink_open_table(name_lock);
2140
 
      }
2141
 
 
2142
 
      return res;
2143
 
    }
2144
 
 
2145
 
    if (not name_lock)
2146
 
    {
2147
 
      table_exists= true;
2148
 
    }
2149
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2150
 
    {
2151
 
      table_exists= true;
2152
 
    }
2153
 
    else // Otherwise we create the table
2154
 
    {
2155
 
      bool was_created;
2156
 
      {
2157
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
 
                                          source_identifier, is_engine_set);
2160
 
      }
2161
 
 
2162
 
      // So we blew the creation of the table, and we scramble to clean up
2163
 
      // anything that might have been created (read... it is a hack)
2164
 
      if (not was_created)
2165
 
      {
2166
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2167
 
      } 
2168
 
      else
2169
 
      {
2170
 
        res= false;
2171
 
      }
2172
 
    }
2173
 
 
2174
 
    if (name_lock)
2175
 
    {
2176
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2177
 
      session->unlink_open_table(name_lock);
2178
 
    }
2179
 
  }
2180
 
 
2181
 
  if (table_exists)
2182
 
  {
2183
 
    if (is_if_not_exists)
2184
 
    {
2185
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
 
      snprintf(warn_buff, sizeof(warn_buff),
2187
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2188
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2190
 
      return false;
2191
 
    }
2192
 
 
2193
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2194
 
 
2195
 
    return true;
2196
 
  }
2197
 
 
2198
 
  return res;
2199
 
}
2200
 
 
2201
 
 
2202
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
 
{
2204
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
 
 
2206
 
  return(admin_table(session, tables, check_opt,
2207
 
                                "analyze", lock_type, true,
2208
 
                                &Cursor::ha_analyze));
2209
 
}
2210
 
 
2211
 
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
 
{
2214
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
 
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2533
      protoerr= plugins.storage_engine.getTableProto(src_path, &src_proto);
 
2534
    }
 
2535
 
 
2536
    string dst_proto_path(dst_path);
 
2537
    string file_ext = ".dfe";
 
2538
 
 
2539
    dst_proto_path.append(file_ext);
 
2540
 
 
2541
    if (protoerr == EEXIST)
 
2542
    {
 
2543
      plugin::StorageEngine* engine= ha_resolve_by_name(session,
 
2544
                                                src_proto.engine().name());
 
2545
 
 
2546
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2547
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &src_proto);
 
2548
      else
 
2549
        protoerr= 0;
 
2550
    }
 
2551
 
 
2552
    if (protoerr)
 
2553
    {
 
2554
      if (my_errno == ENOENT)
 
2555
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2556
      else
 
2557
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2558
      pthread_mutex_unlock(&LOCK_open);
 
2559
      goto err;
 
2560
    }
 
2561
  }
 
2562
 
 
2563
  /*
 
2564
    As mysql_truncate don't work on a new table at this stage of
 
2565
    creation, instead create the table directly (for both normal
 
2566
    and temporary tables).
 
2567
  */
 
2568
 
 
2569
  err= ha_create_table(session, dst_path, db, table_name, create_info, 1,
 
2570
                       &src_proto);
 
2571
  pthread_mutex_unlock(&LOCK_open);
 
2572
 
 
2573
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2574
  {
 
2575
    if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
 
2576
    {
 
2577
      (void) session->rm_temporary_table(create_info->db_type, dst_path);
 
2578
      goto err;
 
2579
    }
 
2580
  }
 
2581
  else if (err)
 
2582
  {
 
2583
    (void) quick_rm_table(create_info->db_type, db,
 
2584
                          table_name, false);
 
2585
    goto err;
 
2586
  }
 
2587
 
 
2588
  /*
 
2589
    We have to write the query before we unlock the tables.
 
2590
  */
 
2591
  {
 
2592
    /*
 
2593
       Since temporary tables are not replicated under row-based
 
2594
       replication, CREATE TABLE ... LIKE ... needs special
 
2595
       treatement.  We have four cases to consider, according to the
 
2596
       following decision table:
 
2597
 
 
2598
           ==== ========= ========= ==============================
 
2599
           Case    Target    Source Write to binary log
 
2600
           ==== ========= ========= ==============================
 
2601
           1       normal    normal Original statement
 
2602
           2       normal temporary Generated statement
 
2603
           3    temporary    normal Nothing
 
2604
           4    temporary temporary Nothing
 
2605
           ==== ========= ========= ==============================
 
2606
    */
 
2607
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2608
    {
 
2609
      if (src_table->table->s->tmp_table)               // Case 2
 
2610
      {
 
2611
        char buf[2048];
 
2612
        String query(buf, sizeof(buf), system_charset_info);
 
2613
        query.length(0);  // Have to zero it since constructor doesn't
 
2614
 
 
2615
 
 
2616
        /*
 
2617
          Here we open the destination table, on which we already have
 
2618
          name-lock. This is needed for store_create_info() to work.
 
2619
          The table will be closed by unlink_open_table() at the end
 
2620
          of this function.
 
2621
        */
 
2622
        table->table= name_lock;
 
2623
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2624
        if (session->reopen_name_locked_table(table, false))
 
2625
        {
 
2626
          pthread_mutex_unlock(&LOCK_open);
 
2627
          goto err;
 
2628
        }
 
2629
        pthread_mutex_unlock(&LOCK_open);
 
2630
 
 
2631
        int result= store_create_info(table, &query, create_info);
 
2632
 
 
2633
        assert(result == 0); // store_create_info() always return 0
 
2634
        write_bin_log(session, true, query.ptr(), query.length());
 
2635
      }
 
2636
      else                                      // Case 1
 
2637
        write_bin_log(session, true, session->query, session->query_length);
 
2638
    }
 
2639
  }
 
2640
 
 
2641
  res= false;
 
2642
  goto err;
 
2643
 
 
2644
table_exists:
 
2645
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2646
  {
 
2647
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2648
    snprintf(warn_buff, sizeof(warn_buff),
 
2649
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2650
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2651
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2652
    res= false;
 
2653
  }
 
2654
  else
 
2655
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2656
 
 
2657
err:
 
2658
  if (name_lock)
 
2659
  {
 
2660
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2661
    session->unlink_open_table(name_lock);
 
2662
    pthread_mutex_unlock(&LOCK_open);
 
2663
  }
 
2664
  return(res);
 
2665
}
 
2666
 
 
2667
 
 
2668
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2669
{
 
2670
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
2671
 
 
2672
  return(mysql_admin_table(session, tables, check_opt,
 
2673
                                "analyze", lock_type, 1, 0, 0, 0,
 
2674
                                &handler::ha_analyze));
 
2675
}
 
2676
 
 
2677
 
 
2678
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2679
{
 
2680
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
2681
 
 
2682
  return(mysql_admin_table(session, tables, check_opt,
2217
2683
                                "check", lock_type,
2218
 
                                false,
2219
 
                                &Cursor::ha_check));
2220
 
}
2221
 
 
2222
 
} /* namespace drizzled */
 
2684
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
2685
                                &handler::ha_check));
 
2686
}
 
2687
 
 
2688
/*
 
2689
  Recreates tables by calling mysql_alter_table().
 
2690
 
 
2691
  SYNOPSIS
 
2692
    mysql_recreate_table()
 
2693
    session                     Thread handler
 
2694
    tables              Tables to recreate
 
2695
 
 
2696
 RETURN
 
2697
    Like mysql_alter_table().
 
2698
*/
 
2699
bool mysql_recreate_table(Session *session, TableList *table_list)
 
2700
{
 
2701
  HA_CREATE_INFO create_info;
 
2702
  AlterInfo alter_info;
 
2703
  message::Table table_proto;
 
2704
 
 
2705
  assert(!table_list->next_global);
 
2706
  /*
 
2707
    table_list->table has been closed and freed. Do not reference
 
2708
    uninitialized data. open_tables() could fail.
 
2709
  */
 
2710
  table_list->table= NULL;
 
2711
 
 
2712
  memset(&create_info, 0, sizeof(create_info));
 
2713
  create_info.row_type=ROW_TYPE_NOT_USED;
 
2714
  create_info.default_table_charset=default_charset_info;
 
2715
  /* Force alter table to recreate table */
 
2716
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
2717
  alter_info.flags.set(ALTER_RECREATE);
 
2718
  return(mysql_alter_table(session, NULL, NULL, &create_info, &table_proto,
 
2719
                           table_list, &alter_info, 0,
 
2720
                           (order_st *) 0, 0));
 
2721
}
 
2722
 
 
2723
 
 
2724
bool mysql_checksum_table(Session *session, TableList *tables,
 
2725
                          HA_CHECK_OPT *check_opt)
 
2726
{
 
2727
  TableList *table;
 
2728
  List<Item> field_list;
 
2729
  Item *item;
 
2730
 
 
2731
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
2732
  item->maybe_null= 1;
 
2733
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
2734
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
2735
  item->maybe_null= 1;
 
2736
  if (session->client->sendFields(&field_list))
 
2737
    return true;
 
2738
 
 
2739
  /* Open one table after the other to keep lock time as short as possible. */
 
2740
  for (table= tables; table; table= table->next_local)
 
2741
  {
 
2742
    char table_name[NAME_LEN*2+2];
 
2743
    Table *t;
 
2744
 
 
2745
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2746
 
 
2747
    t= table->table= session->openTableLock(table, TL_READ);
 
2748
    session->clear_error();                     // these errors shouldn't get client
 
2749
 
 
2750
    session->client->store(table_name);
 
2751
 
 
2752
    if (!t)
 
2753
    {
 
2754
      /* Table didn't exist */
 
2755
      session->client->store();
 
2756
      session->clear_error();
 
2757
    }
 
2758
    else
 
2759
    {
 
2760
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
2761
          !(check_opt->flags & T_EXTEND))
 
2762
        session->client->store((uint64_t)t->file->checksum());
 
2763
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
2764
               (check_opt->flags & T_QUICK))
 
2765
        session->client->store();
 
2766
      else
 
2767
      {
 
2768
        /* calculating table's checksum */
 
2769
        ha_checksum crc= 0;
 
2770
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2771
 
 
2772
        t->use_all_columns();
 
2773
 
 
2774
        if (t->file->ha_rnd_init(1))
 
2775
          session->client->store();
 
2776
        else
 
2777
        {
 
2778
          for (;;)
 
2779
          {
 
2780
            ha_checksum row_crc= 0;
 
2781
            int error= t->file->rnd_next(t->record[0]);
 
2782
            if (unlikely(error))
 
2783
            {
 
2784
              if (error == HA_ERR_RECORD_DELETED)
 
2785
                continue;
 
2786
              break;
 
2787
            }
 
2788
            if (t->s->null_bytes)
 
2789
            {
 
2790
              /* fix undefined null bits */
 
2791
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
2792
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
2793
                t->record[0][0] |= 1;
 
2794
 
 
2795
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
2796
            }
 
2797
 
 
2798
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
2799
            {
 
2800
              Field *f= t->field[i];
 
2801
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
2802
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
2803
              {
 
2804
                String tmp;
 
2805
                f->val_str(&tmp);
 
2806
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
2807
              }
 
2808
              else
 
2809
                row_crc= my_checksum(row_crc, f->ptr,
 
2810
                                     f->pack_length());
 
2811
            }
 
2812
 
 
2813
            crc+= row_crc;
 
2814
          }
 
2815
          session->client->store((uint64_t)crc);
 
2816
          t->file->ha_rnd_end();
 
2817
        }
 
2818
      }
 
2819
      session->clear_error();
 
2820
      session->close_thread_tables();
 
2821
      table->table=0;                           // For query cache
 
2822
    }
 
2823
    if (session->client->flush())
 
2824
      goto err;
 
2825
  }
 
2826
 
 
2827
  session->my_eof();
 
2828
  return(false);
 
2829
 
 
2830
 err:
 
2831
  session->close_thread_tables();                       // Shouldn't be needed
 
2832
  if (table)
 
2833
    table->table=0;
 
2834
  return(true);
 
2835
}
 
2836
 
 
2837
bool check_engine(Session *session, const char *table_name,
 
2838
                         HA_CREATE_INFO *create_info)
 
2839
{
 
2840
  plugin::StorageEngine **new_engine= &create_info->db_type;
 
2841
  plugin::StorageEngine *req_engine= *new_engine;
 
2842
  if (!req_engine->is_enabled())
 
2843
  {
 
2844
    string engine_name= req_engine->getName();
 
2845
    my_error(ER_FEATURE_DISABLED,MYF(0),
 
2846
             engine_name.c_str(), engine_name.c_str());
 
2847
             
 
2848
    return true;
 
2849
  }
 
2850
 
 
2851
  if (req_engine && req_engine != *new_engine)
 
2852
  {
 
2853
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2854
                       ER_WARN_USING_OTHER_HANDLER,
 
2855
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
2856
                       ha_resolve_storage_engine_name(*new_engine).c_str(),
 
2857
                       table_name);
 
2858
  }
 
2859
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
2860
      (*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
 
2861
  {
 
2862
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
2863
    {
 
2864
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2865
               ha_resolve_storage_engine_name(*new_engine).c_str(),
 
2866
               "TEMPORARY");
 
2867
      *new_engine= 0;
 
2868
      return true;
 
2869
    }
 
2870
    *new_engine= myisam_engine;
 
2871
  }
 
2872
  if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2873
     && (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
 
2874
  {
 
2875
    my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2876
             ha_resolve_storage_engine_name(*new_engine).c_str(),
 
2877
             "non-TEMPORARY");
 
2878
    *new_engine= 0;
 
2879
    return true;
 
2880
  }
 
2881
 
 
2882
  return false;
 
2883
}