~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2009-12-25 08:50:15 UTC
  • mto: This revision was merged to the branch mainline in revision 1255.
  • Revision ID: mordred@inaugust.com-20091225085015-83sux5qsvy312gew
MEM_ROOT == memory::Root

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
 
32
32
#include <drizzled/unireg.h>
33
33
#include <drizzled/item/int.h>
34
34
#include <drizzled/item/empty_string.h>
35
 
#include <drizzled/transaction_services.h>
36
 
#include "drizzled/transaction_services.h"
 
35
#include <drizzled/replication_services.h>
37
36
#include <drizzled/table_proto.h>
38
37
#include <drizzled/plugin/client.h>
39
 
#include <drizzled/identifier.h>
 
38
#include <drizzled/table_identifier.h>
40
39
#include "drizzled/internal/m_string.h"
41
40
#include "drizzled/global_charset_info.h"
42
41
#include "drizzled/charset.h"
43
42
 
44
 
#include "drizzled/definition/cache.h"
45
 
 
46
43
 
47
44
#include "drizzled/statement/alter_table.h"
 
45
#include "drizzled/plugin/info_schema_table.h"
48
46
#include "drizzled/sql_table.h"
49
47
#include "drizzled/pthread_globals.h"
50
 
#include "drizzled/plugin/storage_engine.h"
51
48
 
52
49
#include <algorithm>
53
50
#include <sstream>
54
51
 
55
 
#include <boost/unordered_set.hpp>
56
 
 
57
52
using namespace std;
58
 
 
59
 
namespace drizzled
60
 
{
61
 
 
62
 
bool is_primary_key(KeyInfo *key_info)
 
53
using namespace drizzled;
 
54
 
 
55
extern pid_t current_pid;
 
56
 
 
57
static const char hexchars[]= "0123456789abcdef";
 
58
bool is_primary_key(KEY *key_info)
63
59
{
64
60
  static const char * primary_key_name="PRIMARY";
65
61
  return (strcmp(key_info->name, primary_key_name)==0);
74
70
    return NULL;
75
71
}
76
72
 
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);
 
73
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
74
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
79
75
 
80
76
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
77
 
86
82
    let's fetch the database default character set and
87
83
    apply it to the table.
88
84
  */
89
 
  identifier::Schema identifier(db);
90
85
  if (create_info->default_table_charset == NULL)
91
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
86
    create_info->default_table_charset= get_default_db_collation(db);
 
87
}
 
88
 
 
89
/*
 
90
  Translate a cursor name to a table name (WL #1324).
 
91
 
 
92
  SYNOPSIS
 
93
    filename_to_tablename()
 
94
      from                      The cursor name
 
95
      to                OUT     The table name
 
96
      to_length                 The size of the table name buffer.
 
97
 
 
98
  RETURN
 
99
    Table name length.
 
100
*/
 
101
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
102
{
 
103
  uint32_t length= 0;
 
104
 
 
105
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
106
  {
 
107
    /* Temporary table name. */
 
108
    length= strlen(strncpy(to, from, to_length));
 
109
  }
 
110
  else
 
111
  {
 
112
    for (; *from  && length < to_length; length++, from++)
 
113
    {
 
114
      if (*from != '@')
 
115
      {
 
116
        to[length]= *from;
 
117
        continue;
 
118
      }
 
119
      /* We've found an escaped char - skip the @ */
 
120
      from++;
 
121
      to[length]= 0;
 
122
      /* There will be a two-position hex-char version of the char */
 
123
      for (int x=1; x >= 0; x--)
 
124
      {
 
125
        if (*from >= '0' && *from <= '9')
 
126
          to[length] += ((*from++ - '0') << (4 * x));
 
127
        else if (*from >= 'a' && *from <= 'f')
 
128
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
129
      }
 
130
      /* Backup because we advanced extra in the inner loop */
 
131
      from--;
 
132
    } 
 
133
  }
 
134
 
 
135
  return length;
 
136
}
 
137
 
 
138
 
 
139
/*
 
140
  Translate a table name to a cursor name (WL #1324).
 
141
 
 
142
  SYNOPSIS
 
143
    tablename_to_filename()
 
144
      from                      The table name
 
145
      to                OUT     The cursor name
 
146
      to_length                 The size of the cursor name buffer.
 
147
 
 
148
  RETURN
 
149
    true if errors happen. false on success.
 
150
*/
 
151
bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
152
{
 
153
  
 
154
  size_t length= 0;
 
155
  for (; *from  && length < to_length; length++, from++)
 
156
  {
 
157
    if ((*from >= '0' && *from <= '9') ||
 
158
        (*from >= 'A' && *from <= 'Z') ||
 
159
        (*from >= 'a' && *from <= 'z') ||
 
160
/* OSX defines an extra set of high-bit and multi-byte characters
 
161
   that cannot be used on the filesystem. Instead of trying to sort
 
162
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
163
   It won't really hurt anything - it'll just make some filenames ugly. */
 
164
#if !defined(TARGET_OS_OSX)
 
165
        ((unsigned char)*from >= 128) ||
 
166
#endif
 
167
        (*from == '_') ||
 
168
        (*from == ' ') ||
 
169
        (*from == '-'))
 
170
    {
 
171
      to[length]= *from;
 
172
      continue;
 
173
    }
 
174
   
 
175
    if (length + 3 >= to_length)
 
176
      return true;
 
177
 
 
178
    /* We need to escape this char in a way that can be reversed */
 
179
    to[length++]= '@';
 
180
    to[length++]= hexchars[(*from >> 4) & 15];
 
181
    to[length]= hexchars[(*from) & 15];
 
182
  }
 
183
 
 
184
  if (check_if_legal_tablename(to) &&
 
185
      length + 4 < to_length)
 
186
  {
 
187
    memcpy(to + length, "@@@", 4);
 
188
    length+= 3;
 
189
  }
 
190
  return false;
 
191
}
 
192
 
 
193
 
 
194
/*
 
195
  Creates path to a cursor: drizzle_data_dir/db/table.ext
 
196
 
 
197
  SYNOPSIS
 
198
   build_table_filename()
 
199
     buff                       Where to write result
 
200
                                This may be the same as table_name.
 
201
     bufflen                    buff size
 
202
     db                         Database name
 
203
     table_name                 Table name
 
204
     ext                        File extension.
 
205
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP
 
206
                                table_name is temporary, do not change.
 
207
 
 
208
  NOTES
 
209
 
 
210
    Uses database and table name, and extension to create
 
211
    a cursor name in drizzle_data_dir. Database and table
 
212
    names are converted from system_charset_info into "fscs".
 
213
    Unless flags indicate a temporary table name.
 
214
    'db' is always converted.
 
215
    'ext' is not converted.
 
216
 
 
217
    The conversion suppression is required for ALTER Table. This
 
218
    statement creates intermediate tables. These are regular
 
219
    (non-temporary) tables with a temporary name. Their path names must
 
220
    be derivable from the table name. So we cannot use
 
221
    build_tmptable_filename() for them.
 
222
 
 
223
  RETURN
 
224
    path length on success, 0 on failure
 
225
*/
 
226
 
 
227
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
 
228
{
 
229
  char dbbuff[FN_REFLEN];
 
230
  char tbbuff[FN_REFLEN];
 
231
  bool conversion_error= false;
 
232
 
 
233
  memset(tbbuff, 0, sizeof(tbbuff));
 
234
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
235
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
236
  else
 
237
  {
 
238
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
239
    if (conversion_error)
 
240
    {
 
241
      errmsg_printf(ERRMSG_LVL_ERROR,
 
242
                    _("Table name cannot be encoded and fit within filesystem "
 
243
                      "name length restrictions."));
 
244
      return 0;
 
245
    }
 
246
  }
 
247
  memset(dbbuff, 0, sizeof(dbbuff));
 
248
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
249
  if (conversion_error)
 
250
  {
 
251
    errmsg_printf(ERRMSG_LVL_ERROR,
 
252
                  _("Schema name cannot be encoded and fit within filesystem "
 
253
                    "name length restrictions."));
 
254
    return 0;
 
255
  }
 
256
   
 
257
 
 
258
  int rootdir_len= strlen(FN_ROOTDIR);
 
259
  string table_path(drizzle_data_home);
 
260
  int without_rootdir= table_path.length()-rootdir_len;
 
261
 
 
262
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
263
  if (without_rootdir >= 0)
 
264
  {
 
265
    const char *tmp= table_path.c_str()+without_rootdir;
 
266
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
267
      table_path.append(FN_ROOTDIR);
 
268
  }
 
269
 
 
270
  table_path.append(dbbuff);
 
271
  table_path.append(FN_ROOTDIR);
 
272
  table_path.append(tbbuff);
 
273
 
 
274
  if (bufflen < table_path.length())
 
275
    return 0;
 
276
 
 
277
  strcpy(buff, table_path.c_str());
 
278
 
 
279
  return table_path.length();
 
280
}
 
281
 
 
282
 
 
283
/*
 
284
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
 
285
 
 
286
  SYNOPSIS
 
287
   build_tmptable_filename()
 
288
     session                    The thread handle.
 
289
     buff                       Where to write result
 
290
     bufflen                    buff size
 
291
 
 
292
  NOTES
 
293
 
 
294
    Uses current_pid, thread_id, and tmp_table counter to create
 
295
    a cursor name in drizzle_tmpdir.
 
296
 
 
297
  RETURN
 
298
    path length on success, 0 on failure
 
299
*/
 
300
 
 
301
size_t build_tmptable_filename(char *buff, size_t bufflen)
 
302
{
 
303
  size_t length;
 
304
  ostringstream path_str, post_tmpdir_str;
 
305
  string tmp;
 
306
 
 
307
  Session *session= current_session;
 
308
 
 
309
  path_str << drizzle_tmpdir;
 
310
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
311
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
312
  tmp= post_tmpdir_str.str();
 
313
 
 
314
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
315
 
 
316
  path_str << tmp;
 
317
 
 
318
  if (bufflen < path_str.str().length())
 
319
    length= 0;
 
320
  else
 
321
    length= unpack_filename(buff, path_str.str().c_str());
 
322
 
 
323
  return length;
92
324
}
93
325
 
94
326
/*
106
338
    cursor
107
339
*/
108
340
 
109
 
void write_bin_log(Session *session, const std::string &query)
110
 
{
111
 
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
 
341
void write_bin_log(Session *session,
 
342
                   char const *query, size_t query_length)
 
343
{
 
344
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
345
  replication_services.rawStatement(session, query, query_length);
 
346
}
 
347
 
 
348
 
 
349
/* Should should be refactored to go away */
 
350
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
351
{
 
352
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
353
  string built_query;
 
354
 
 
355
  if (if_exists)
 
356
    built_query.append("DROP TABLE IF EXISTS ");
 
357
  else
 
358
    built_query.append("DROP TABLE ");
 
359
 
 
360
  built_query.append("`");
 
361
  if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
 
362
  {
 
363
    built_query.append(db_name);
 
364
    built_query.append("`.`");
 
365
  }
 
366
 
 
367
  built_query.append(table_name);
 
368
  built_query.append("`");
 
369
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
113
370
}
114
371
 
115
372
/*
116
373
  Execute the drop of a normal or temporary table
117
374
 
118
375
  SYNOPSIS
119
 
    rm_table_part2()
 
376
    mysql_rm_table_part2()
120
377
    session                     Thread Cursor
121
378
    tables              Tables to drop
122
379
    if_exists           If set, don't give an error if table doesn't exists.
123
380
                        In this case we give an warning of level 'NOTE'
124
381
    drop_temporary      Only drop temporary tables
125
382
 
126
 
  @todo
 
383
  TODO:
127
384
    When logging to the binary log, we should log
128
385
    tmp_tables and transactional tables as separate statements if we
129
386
    are in a transaction;  This is needed to get these tables into the
139
396
   -1   Thread was killed
140
397
*/
141
398
 
142
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                   bool drop_temporary)
 
399
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
400
                         bool drop_temporary)
144
401
{
145
402
  TableList *table;
 
403
  char path[FN_REFLEN];
 
404
  uint32_t path_length= 0;
146
405
  String wrong_tables;
147
406
  int error= 0;
148
407
  bool foreign_key_error= false;
149
408
 
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:
 
409
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
410
 
 
411
  /*
 
412
    If we have the table in the definition cache, we don't have to check the
 
413
    .frm cursor to find if the table is a normal table (not view) and what
 
414
    engine to use.
 
415
  */
 
416
 
 
417
  for (table= tables; table; table= table->next_local)
 
418
  {
 
419
    TableShare *share;
 
420
    table->db_type= NULL;
 
421
    if ((share= TableShare::getShare(table->db, table->table_name)))
 
422
      table->db_type= share->db_type();
 
423
  }
 
424
 
 
425
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
426
  {
 
427
    pthread_mutex_unlock(&LOCK_open);
 
428
    return 1;
 
429
  }
 
430
 
 
431
  /* Don't give warnings for not found errors, as we already generate notes */
 
432
  session->no_warnings_for_error= 1;
 
433
 
 
434
  for (table= tables; table; table= table->next_local)
 
435
  {
 
436
    char *db=table->db;
 
437
    plugin::StorageEngine *table_type;
 
438
 
 
439
    error= session->drop_temporary_table(table);
 
440
 
 
441
    switch (error) {
 
442
    case  0:
 
443
      // removed temporary table
 
444
      continue;
 
445
    case -1:
 
446
      error= 1;
 
447
      goto err_with_placeholders;
 
448
    default:
 
449
      // temporary table not found
 
450
      error= 0;
 
451
    }
 
452
 
 
453
    table_type= table->db_type;
 
454
    if (drop_temporary == false)
 
455
    {
 
456
      Table *locked_table;
 
457
      abort_locked_tables(session, db, table->table_name);
 
458
      remove_table_from_cache(session, db, table->table_name,
 
459
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
460
                              RTFC_CHECK_KILLED_FLAG);
 
461
      /*
 
462
        If the table was used in lock tables, remember it so that
 
463
        unlock_table_names can free it
 
464
      */
 
465
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
466
        table->table= locked_table;
 
467
 
 
468
      if (session->killed)
 
469
      {
 
470
        error= -1;
 
471
        goto err_with_placeholders;
 
472
      }
 
473
      /* remove .frm cursor and engine files */
 
474
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
 
475
    }
 
476
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
 
477
 
 
478
    if (drop_temporary ||
 
479
        ((table_type == NULL
 
480
          && (plugin::StorageEngine::getTableDefinition(*session,
 
481
                                                        identifier) != EEXIST))))
 
482
    {
 
483
      // Table was not found on disk and table can't be created from engine
 
484
      if (if_exists)
 
485
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
486
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
487
                            table->table_name);
 
488
      else
173
489
        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
 
 
 
490
    }
 
491
    else
 
492
    {
 
493
      error= plugin::StorageEngine::dropTable(*session,
 
494
                                              identifier,
 
495
                                              true);
 
496
 
 
497
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
498
      {
 
499
        error= 0;
 
500
        session->clear_error();
 
501
      }
 
502
 
 
503
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
504
      {
 
505
        /* the table is referenced by a foreign key constraint */
 
506
        foreign_key_error= true;
 
507
      }
 
508
    }
 
509
 
 
510
    if (error == 0 || (if_exists && foreign_key_error == false))
 
511
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
512
 
 
513
    if (error)
 
514
    {
 
515
      if (wrong_tables.length())
 
516
        wrong_tables.append(',');
 
517
      wrong_tables.append(String(table->table_name,system_charset_info));
 
518
    }
 
519
  }
 
520
  /*
 
521
    It's safe to unlock LOCK_open: we have an exclusive lock
 
522
    on the table name.
 
523
  */
 
524
  pthread_mutex_unlock(&LOCK_open);
 
525
  error= 0;
253
526
  if (wrong_tables.length())
254
527
  {
255
 
    if (not foreign_key_error)
256
 
    {
 
528
    if (!foreign_key_error)
257
529
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
530
                      wrong_tables.c_ptr());
259
 
    }
260
531
    else
261
532
    {
262
533
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
264
535
    error= 1;
265
536
  }
266
537
 
 
538
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
 
539
err_with_placeholders:
 
540
  unlock_table_names(tables, NULL);
 
541
  pthread_mutex_unlock(&LOCK_open);
267
542
  session->no_warnings_for_error= 0;
268
543
 
269
 
  return error;
 
544
  return(error);
 
545
}
 
546
 
 
547
 
 
548
/*
 
549
  Quickly remove a table.
 
550
 
 
551
  SYNOPSIS
 
552
    quick_rm_table()
 
553
      base                      The plugin::StorageEngine handle.
 
554
      db                        The database name.
 
555
      table_name                The table name.
 
556
      is_tmp                    If the table is temp.
 
557
 
 
558
  RETURN
 
559
    0           OK
 
560
    != 0        Error
 
561
*/
 
562
bool quick_rm_table(Session& session,
 
563
                    TableIdentifier &identifier)
 
564
{
 
565
  return (plugin::StorageEngine::dropTable(session, identifier, false));
270
566
}
271
567
 
272
568
/*
282
578
  PRIMARY keys are prioritized.
283
579
*/
284
580
 
285
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
581
static int sort_keys(KEY *a, KEY *b)
286
582
{
287
583
  ulong a_flags= a->flags, b_flags= b->flags;
288
584
 
334
630
    1             Error
335
631
*/
336
632
 
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
633
static bool check_duplicates_in_interval(const char *set_or_name,
372
634
                                         const char *name, TYPELIB *typelib,
373
635
                                         const CHARSET_INFO * const cs,
378
640
  unsigned int *cur_length= typelib->type_lengths;
379
641
  *dup_val_count= 0;
380
642
 
381
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
382
 
 
383
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
643
  for ( ; tmp.count > 1; cur_value++, cur_length++)
384
644
  {
385
645
    tmp.type_names++;
386
646
    tmp.type_lengths++;
387
647
    tmp.count--;
388
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
648
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
389
649
    {
390
650
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
651
               name,*cur_value,set_or_name);
392
652
      return 1;
393
653
    }
394
 
    else
395
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
396
654
  }
397
655
  return 0;
398
656
}
465
723
 
466
724
  switch (sql_field->sql_type) {
467
725
  case DRIZZLE_TYPE_BLOB:
 
726
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
468
727
    sql_field->length= 8; // Unireg field length
469
728
    (*blob_columns)++;
470
729
    break;
471
 
 
 
730
  case DRIZZLE_TYPE_VARCHAR:
 
731
    sql_field->pack_flag=0;
 
732
    break;
472
733
  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:
 
734
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
 
735
    if (check_duplicates_in_interval("ENUM",
 
736
                                     sql_field->field_name,
 
737
                                     sql_field->interval,
 
738
                                     sql_field->charset,
 
739
                                     &dup_val_count))
 
740
      return 1;
 
741
    break;
 
742
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
743
  case DRIZZLE_TYPE_DATETIME:
 
744
  case DRIZZLE_TYPE_NULL:
 
745
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
 
746
    break;
 
747
  case DRIZZLE_TYPE_DECIMAL:
 
748
    sql_field->pack_flag= 0;
 
749
    break;
486
750
  case DRIZZLE_TYPE_TIMESTAMP:
487
751
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
752
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
493
757
        (*timestamps_with_niladic)++;
494
758
      }
495
759
      else
496
 
      {
497
760
        sql_field->unireg_check= Field::NONE;
498
 
      }
499
761
    }
500
762
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
763
      (*timestamps_with_niladic)++;
503
 
    }
504
764
 
505
765
    (*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:
 
766
    /* fall-through */
 
767
  default:
 
768
    sql_field->pack_flag=(0 |
 
769
                          f_settype((uint32_t) sql_field->sql_type));
520
770
    break;
521
771
  }
522
 
 
523
772
  return 0;
524
773
}
525
774
 
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)
 
775
int mysql_prepare_create_table(Session *session,
 
776
                               HA_CREATE_INFO *create_info,
 
777
                               message::Table *create_proto,
 
778
                               AlterInfo *alter_info,
 
779
                               bool tmp_table,
 
780
                               uint32_t *db_options,
 
781
                               Cursor *cursor,
 
782
                               KEY **key_info_buffer,
 
783
                               uint32_t *key_count,
 
784
                               int select_field_count)
535
785
{
536
786
  const char    *key_name;
537
787
  CreateField   *sql_field,*dup_field;
538
788
  uint          field,null_fields,blob_columns,max_key_length;
539
789
  ulong         record_offset= 0;
540
 
  KeyInfo               *key_info;
541
 
  KeyPartInfo *key_part_info;
 
790
  KEY           *key_info;
 
791
  KEY_PART_INFO *key_part_info;
542
792
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
793
  int           field_no,dup_no;
544
794
  int           select_field_pos,auto_increment=0;
545
795
  List_iterator<CreateField> it(alter_info->create_list);
546
796
  List_iterator<CreateField> it2(alter_info->create_list);
547
797
  uint32_t total_uneven_bit_length= 0;
548
798
 
549
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
550
 
 
551
799
  select_field_pos= alter_info->create_list.elements - select_field_count;
552
800
  null_fields=blob_columns=0;
553
 
  max_key_length= engine->max_key_length();
 
801
  max_key_length= cursor->getEngine()->max_key_length();
554
802
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
803
  for (field_no=0; (sql_field=it++) ; field_no++)
556
804
  {
557
805
    const CHARSET_INFO *save_cs;
558
806
 
562
810
      executing a prepared statement for the second time.
563
811
    */
564
812
    sql_field->length= sql_field->char_length;
565
 
 
566
813
    if (!sql_field->charset)
567
814
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
815
    /*
570
816
      table_charset is set in ALTER Table if we want change character set
571
817
      for all varchar/char columns.
618
864
 
619
865
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
866
    {
621
 
      size_t dummy;
 
867
      uint32_t dummy;
622
868
      const CHARSET_INFO * const cs= sql_field->charset;
623
869
      TYPELIB *interval= sql_field->interval;
624
870
 
651
897
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
898
                                       cs, &dummy))
653
899
          {
654
 
            size_t cnv_errs;
 
900
            uint32_t cnv_errs;
655
901
            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());
 
902
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
903
                                                  conv.length());
657
904
            interval->type_lengths[i]= conv.length();
658
905
          }
659
906
 
693
940
            }
694
941
          }
695
942
        }
696
 
        uint32_t new_dummy;
697
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
943
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
698
944
        sql_field->length= field_length;
699
945
      }
700
946
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
758
1004
        }
759
1005
      }
760
1006
    }
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
 
    {
 
1007
    /* Don't pack rows in old tables if the user has requested this */
 
1008
    if ((sql_field->flags & BLOB_FLAG) ||
 
1009
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
767
1010
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
1011
    it2.rewind();
771
1012
  }
772
1013
 
798
1039
    return(true);
799
1040
  }
800
1041
  if (auto_increment &&
801
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1042
      (cursor->getEngine()->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
802
1043
  {
803
1044
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
804
1045
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
805
1046
    return(true);
806
1047
  }
807
1048
 
808
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1049
  if (blob_columns && (cursor->getEngine()->check_flag(HTON_BIT_NO_BLOBS)))
809
1050
  {
810
1051
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
811
1052
               MYF(0));
833
1074
      fk_key_count++;
834
1075
      if (((Foreign_key *)key)->validate(alter_info->create_list))
835
1076
        return true;
836
 
 
837
1077
      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
1078
      if (fk_key->ref_columns.elements &&
849
1079
          fk_key->ref_columns.elements != fk_key->columns.elements)
850
1080
      {
857
1087
      continue;
858
1088
    }
859
1089
    (*key_count)++;
860
 
    tmp= engine->max_key_parts();
 
1090
    tmp=cursor->getEngine()->max_key_parts();
861
1091
    if (key->columns.elements > tmp)
862
1092
    {
863
1093
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
879
1109
             key2->name.str != ignore_key &&
880
1110
             !foreign_key_prefix(key, key2)))
881
1111
        {
882
 
          /* @todo issue warning message */
 
1112
          /* TODO: issue warning message */
883
1113
          /* mark that the generated key should be ignored */
884
1114
          if (!key2->generated ||
885
1115
              (key->generated && key->columns.elements <
906
1136
      return(true);
907
1137
    }
908
1138
  }
909
 
  tmp= engine->max_keys();
 
1139
  tmp=cursor->getEngine()->max_keys();
910
1140
  if (*key_count > tmp)
911
1141
  {
912
1142
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
913
1143
    return(true);
914
1144
  }
915
1145
 
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);
 
1146
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1147
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
918
1148
  if (!*key_info_buffer || ! key_part_info)
919
1149
    return(true);                               // Out of memory
920
1150
 
954
1184
    key_info->usable_key_parts= key_number;
955
1185
    key_info->algorithm= key->key_create_info.algorithm;
956
1186
 
 
1187
    /* Take block size from key part or table part */
 
1188
    /*
 
1189
      TODO: Add warning if block size changes. We can't do it here, as
 
1190
      this may depend on the size of the key
 
1191
    */
 
1192
    key_info->block_size= (key->key_create_info.block_size ?
 
1193
                           key->key_create_info.block_size :
 
1194
                           create_proto->options().key_block_size());
 
1195
 
 
1196
    if (key_info->block_size)
 
1197
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
1198
 
957
1199
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
958
1200
                                           key->key_create_info.comment.str,
959
1201
                                           key->key_create_info.comment.str +
990
1232
             my_strcasecmp(system_charset_info,
991
1233
                           column->field_name.str,
992
1234
                           sql_field->field_name))
993
 
      {
994
1235
        field++;
995
 
      }
996
 
 
997
1236
      if (!sql_field)
998
1237
      {
999
1238
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
1239
        return(true);
1001
1240
      }
1002
 
 
1003
1241
      while ((dup_column= cols2++) != column)
1004
1242
      {
1005
1243
        if (!my_strcasecmp(system_charset_info,
1013
1251
      }
1014
1252
      cols2.rewind();
1015
1253
 
1016
 
      if (create_proto.field_size() > 0)
1017
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
 
1254
      if (create_proto->field_size() > 0)
 
1255
        protofield= create_proto->mutable_field(proto_field_nr - 1);
1018
1256
 
1019
1257
      {
1020
1258
        column->length*= sql_field->charset->mbmaxlen;
1021
1259
 
1022
1260
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1023
1261
        {
1024
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
 
1262
          if (! (cursor->getEngine()->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1025
1263
          {
1026
1264
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1027
1265
            return true;
1032
1270
            return true;
1033
1271
          }
1034
1272
        }
1035
 
 
1036
1273
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
1274
        {
1038
1275
          if (key->type == Key::PRIMARY)
1045
1282
            {
1046
1283
              message::Table::Field::FieldConstraints *constraints;
1047
1284
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
 
1285
              constraints->set_is_nullable(false);
1049
1286
            }
1050
1287
 
1051
1288
          }
1052
1289
          else
1053
1290
          {
1054
1291
            key_info->flags|= HA_NULL_PART_KEY;
1055
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1292
            if (! (cursor->getEngine()->check_flag(HTON_BIT_NULL_IN_KEY)))
1056
1293
            {
1057
1294
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1058
1295
              return true;
1059
1296
            }
1060
1297
          }
1061
1298
        }
1062
 
 
1063
1299
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
1300
        {
1065
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
 
1301
          if (column_nr == 0 || (cursor->getEngine()->check_flag(HTON_BIT_AUTO_PART_KEY)))
1066
1302
            auto_increment--;                   // Field is used
1067
1303
        }
1068
1304
      }
1069
1305
 
1070
1306
      key_part_info->fieldnr= field;
1071
1307
      key_part_info->offset=  (uint16_t) sql_field->offset;
1072
 
      key_part_info->key_type= 0;
 
1308
      key_part_info->key_type=sql_field->pack_flag;
1073
1309
      length= sql_field->key_length;
1074
1310
 
1075
1311
      if (column->length)
1077
1313
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1078
1314
        {
1079
1315
          if ((length=column->length) > max_key_length ||
1080
 
              length > engine->max_key_part_length())
 
1316
              length > cursor->getEngine()->max_key_part_length())
1081
1317
          {
1082
 
            length= min(max_key_length, engine->max_key_part_length());
 
1318
            length= min(max_key_length, cursor->getEngine()->max_key_part_length());
1083
1319
            if (key->type == Key::MULTIPLE)
1084
1320
            {
1085
1321
              /* not a critical problem */
1104
1340
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1105
1341
          return(true);
1106
1342
        }
1107
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
 
1343
        else if (! (cursor->getEngine()->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1108
1344
        {
1109
1345
          length=column->length;
1110
1346
        }
1114
1350
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1115
1351
          return(true);
1116
1352
      }
1117
 
      if (length > engine->max_key_part_length())
 
1353
      if (length > cursor->getEngine()->max_key_part_length())
1118
1354
      {
1119
 
        length= engine->max_key_part_length();
 
1355
        length= cursor->getEngine()->max_key_part_length();
1120
1356
        if (key->type == Key::MULTIPLE)
1121
1357
        {
1122
1358
          /* not a critical problem */
1137
1373
      key_part_info->length=(uint16_t) length;
1138
1374
      /* Use packed keys for long strings on the first column */
1139
1375
      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)))
 
1376
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1377
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1378
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1143
1379
      {
1144
1380
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1145
1381
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1146
 
        {
1147
1382
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1148
 
        }
1149
1383
        else
1150
 
        {
1151
1384
          key_info->flags|= HA_PACK_KEY;
1152
 
        }
1153
1385
      }
1154
1386
      /* Check if the key segment is partial, set the key flag accordingly */
1155
1387
      if (length != sql_field->key_length)
1184
1416
        key_info->name=(char*) key_name;
1185
1417
      }
1186
1418
    }
1187
 
 
1188
1419
    if (!key_info->name || check_column_name(key_info->name))
1189
1420
    {
1190
1421
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1422
      return(true);
1192
1423
    }
1193
 
 
1194
1424
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1425
      unique_key=1;
1197
 
    }
1198
 
 
1199
1426
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1427
    if (key_length > max_key_length)
1202
1428
    {
1203
1429
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1430
      return(true);
1205
1431
    }
1206
 
 
1207
1432
    key_info++;
1208
1433
  }
1209
 
 
1210
1434
  if (!unique_key && !primary_key &&
1211
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1435
      (cursor->getEngine()->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1212
1436
  {
1213
1437
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1438
    return(true);
1215
1439
  }
1216
 
 
1217
1440
  if (auto_increment > 0)
1218
1441
  {
1219
1442
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1220
1443
    return(true);
1221
1444
  }
1222
1445
  /* Sort keys in optimized order */
1223
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1224
 
                     (qsort_cmp) sort_keys);
 
1446
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1447
           (qsort_cmp) sort_keys);
1225
1448
 
1226
1449
  /* Check fields. */
1227
1450
  it.rewind();
1294
1517
  return 0;
1295
1518
}
1296
1519
 
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
1520
 
1399
1521
/*
1400
1522
  Ignore the name of this function... it locks :(
1402
1524
  Create a table
1403
1525
 
1404
1526
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1527
    mysql_create_table_no_lock()
1406
1528
    session                     Thread object
1407
1529
    db                  Database
1408
1530
    table_name          Table name
1418
1540
 
1419
1541
    Note that this function assumes that caller already have taken
1420
1542
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1543
    that concurrent operations won't intervene. mysql_create_table()
1422
1544
    is a wrapper that can be used for this.
1423
1545
 
1424
1546
  RETURN VALUES
1426
1548
    true  error
1427
1549
*/
1428
1550
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1551
bool mysql_create_table_no_lock(Session *session,
 
1552
                                TableIdentifier &identifier,
1431
1553
                                HA_CREATE_INFO *create_info,
1432
 
                                message::Table &table_proto,
 
1554
                                message::Table *table_proto,
1433
1555
                                AlterInfo *alter_info,
1434
1556
                                bool internal_tmp_table,
1435
1557
                                uint32_t select_field_count,
1436
1558
                                bool is_if_not_exists)
1437
1559
{
1438
1560
  uint          db_options, key_count;
1439
 
  KeyInfo               *key_info_buffer;
 
1561
  KEY           *key_info_buffer;
 
1562
  Cursor        *cursor;
1440
1563
  bool          error= true;
 
1564
  TableShare share;
 
1565
  bool lex_identified_temp_table=
 
1566
    (table_proto->type() == drizzled::message::Table::TEMPORARY);
1441
1567
 
1442
1568
  /* Check for duplicate fields and check type of table to create */
1443
 
  if (not alter_info->create_list.elements)
 
1569
  if (!alter_info->create_list.elements)
1444
1570
  {
1445
1571
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1446
1572
               MYF(0));
1447
1573
    return true;
1448
1574
  }
1449
 
  assert(identifier.getTableName() == table_proto.name());
 
1575
  assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
1450
1576
  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
 
 
1473
 
  session->set_proc_info("After create");
1474
 
 
1475
 
  return(error);
1476
 
}
1477
 
 
1478
 
/**
1479
 
  @note the following two methods implement create [temporary] table.
1480
 
*/
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)
1489
 
{
1490
 
  Table *name_lock= NULL;
1491
 
  bool result;
1492
 
 
1493
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1494
 
  {
1495
 
    result= true;
1496
 
  }
1497
 
  else if (name_lock == NULL)
 
1577
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1578
    db_options|=HA_OPTION_PACK_RECORD;
 
1579
  if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
 
1580
  {
 
1581
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
 
1582
    return true;
 
1583
  }
 
1584
 
 
1585
  set_table_default_charset(create_info, identifier.getDBName());
 
1586
 
 
1587
  /* Check if table exists */
 
1588
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1589
                                 internal_tmp_table,
 
1590
                                 &db_options, cursor,
 
1591
                                 &key_info_buffer, &key_count,
 
1592
                                 select_field_count))
 
1593
    goto err;
 
1594
 
 
1595
  /* Check if table already exists */
 
1596
  if (lex_identified_temp_table &&
 
1597
      session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1498
1598
  {
1499
1599
    if (is_if_not_exists)
1500
1600
    {
 
1601
      create_info->table_existed= 1;            // Mark that table existed
1501
1602
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
1603
                          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);
1510
 
      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
 
 
1525
 
  if (name_lock)
1526
 
  {
1527
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1528
 
    session->unlink_open_table(name_lock);
1529
 
  }
1530
 
 
1531
 
  return(result);
 
1604
                          identifier.getTableName());
 
1605
      error= 0;
 
1606
      goto err;
 
1607
    }
 
1608
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1609
    goto err;
 
1610
  }
 
1611
 
 
1612
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1613
  if (!internal_tmp_table && ! lex_identified_temp_table)
 
1614
  {
 
1615
    if (plugin::StorageEngine::getTableDefinition(*session,
 
1616
                                                  identifier)==EEXIST)
 
1617
    {
 
1618
      if (is_if_not_exists)
 
1619
      {
 
1620
        error= false;
 
1621
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1622
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1623
                            identifier.getTableName());
 
1624
        create_info->table_existed= 1;          // Mark that table existed
 
1625
      }
 
1626
      else 
 
1627
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1628
 
 
1629
      goto unlock_and_end;
 
1630
    }
 
1631
    /*
 
1632
      We don't assert here, but check the result, because the table could be
 
1633
      in the table definition cache and in the same time the .frm could be
 
1634
      missing from the disk, in case of manual intervention which deletes
 
1635
      the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
 
1636
      Then she could create the table. This case is pretty obscure and
 
1637
      therefore we don't introduce a new error message only for it.
 
1638
    */
 
1639
    if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
 
1640
    {
 
1641
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1642
      goto unlock_and_end;
 
1643
    }
 
1644
  }
 
1645
 
 
1646
  /*
 
1647
    Check that table with given name does not already
 
1648
    exist in any storage engine. In such a case it should
 
1649
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1650
    unless user specified CREATE TABLE IF EXISTS
 
1651
    The LOCK_open mutex has been locked to make sure no
 
1652
    one else is attempting to discover the table. Since
 
1653
    it's not on disk as a frm cursor, no one could be using it!
 
1654
  */
 
1655
  if (! lex_identified_temp_table)
 
1656
  {
 
1657
    int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
 
1658
 
 
1659
    switch (retcode)
 
1660
    {
 
1661
      case ENOENT:
 
1662
        /* Normal case, no table exists. we can go and create it */
 
1663
        break;
 
1664
      case EEXIST:
 
1665
        if (is_if_not_exists)
 
1666
        {
 
1667
          error= false;
 
1668
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1669
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1670
                              identifier.getTableName());
 
1671
          create_info->table_existed= 1;                // Mark that table existed
 
1672
          goto unlock_and_end;
 
1673
        }
 
1674
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1675
        goto unlock_and_end;
 
1676
      default:
 
1677
        my_error(retcode, MYF(0), identifier.getTableName());
 
1678
        goto unlock_and_end;
 
1679
    }
 
1680
  }
 
1681
 
 
1682
  session->set_proc_info("creating table");
 
1683
  create_info->table_existed= 0;                // Mark that table is created
 
1684
 
 
1685
  create_info->table_options= db_options;
 
1686
 
 
1687
  if (rea_create_table(session, identifier,
 
1688
                       table_proto,
 
1689
                       create_info, alter_info->create_list,
 
1690
                       key_count, key_info_buffer))
 
1691
    goto unlock_and_end;
 
1692
 
 
1693
  if (lex_identified_temp_table)
 
1694
  {
 
1695
    /* Open table and put in temporary table list */
 
1696
    if (!(session->open_temporary_table(identifier)))
 
1697
    {
 
1698
      (void) session->rm_temporary_table(create_info->db_type, identifier);
 
1699
      goto unlock_and_end;
 
1700
    }
 
1701
  }
 
1702
 
 
1703
  /*
 
1704
    Don't write statement if:
 
1705
    - It is an internal temporary table,
 
1706
    - Row-based logging is used and it we are creating a temporary table, or
 
1707
    - The binary log is not open.
 
1708
    Otherwise, the statement shall be binlogged.
 
1709
   */
 
1710
  if (!internal_tmp_table && ! lex_identified_temp_table)
 
1711
    write_bin_log(session, session->query, session->query_length);
 
1712
  error= false;
 
1713
unlock_and_end:
 
1714
  pthread_mutex_unlock(&LOCK_open);
 
1715
 
 
1716
err:
 
1717
  session->set_proc_info("After create");
 
1718
  delete cursor;
 
1719
  return(error);
1532
1720
}
1533
1721
 
1534
1722
 
1535
1723
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
 
1724
  Database locking aware wrapper for mysql_create_table_no_lock(),
1537
1725
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
 
1726
 
 
1727
bool mysql_create_table(Session *session,
 
1728
                        TableIdentifier &identifier,
1540
1729
                        HA_CREATE_INFO *create_info,
1541
 
                        message::Table &table_proto,
 
1730
                        message::Table *table_proto,
1542
1731
                        AlterInfo *alter_info,
1543
1732
                        bool internal_tmp_table,
1544
1733
                        uint32_t select_field_count,
1545
1734
                        bool is_if_not_exists)
1546
1735
{
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);
 
1736
  Table *name_lock= NULL;
 
1737
  bool result;
 
1738
  bool lex_identified_temp_table=
 
1739
    (table_proto->type() == drizzled::message::Table::TEMPORARY);
 
1740
 
 
1741
  if (! lex_identified_temp_table)
 
1742
  {
 
1743
    if (session->lock_table_name_if_not_cached(identifier.getDBName(),
 
1744
                                               identifier.getTableName(),
 
1745
                                               &name_lock))
 
1746
    {
 
1747
      result= true;
 
1748
      goto unlock;
 
1749
    }
 
1750
    if (name_lock == NULL)
 
1751
    {
 
1752
      if (is_if_not_exists)
 
1753
      {
 
1754
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1755
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1756
                            identifier.getTableName());
 
1757
        create_info->table_existed= 1;
 
1758
        result= false;
 
1759
      }
 
1760
      else
 
1761
      {
 
1762
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1763
        result= true;
 
1764
      }
 
1765
      goto unlock;
 
1766
    }
 
1767
  }
 
1768
 
 
1769
  result= mysql_create_table_no_lock(session,
 
1770
                                     identifier,
 
1771
                                     create_info,
 
1772
                                     table_proto,
 
1773
                                     alter_info,
 
1774
                                     internal_tmp_table,
 
1775
                                     select_field_count,
 
1776
                                     is_if_not_exists);
 
1777
 
 
1778
unlock:
 
1779
  if (name_lock)
 
1780
  {
 
1781
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
 
1782
    session->unlink_open_table(name_lock);
 
1783
    pthread_mutex_unlock(&LOCK_open);
 
1784
  }
 
1785
 
 
1786
  return(result);
1567
1787
}
1568
1788
 
1569
1789
 
1572
1792
**/
1573
1793
 
1574
1794
static bool
1575
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1795
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1576
1796
{
1577
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1797
  for (KEY *key=start ; key != end ; key++)
1578
1798
    if (!my_strcasecmp(system_charset_info,name,key->name))
1579
1799
      return 1;
1580
1800
  return 0;
1582
1802
 
1583
1803
 
1584
1804
static char *
1585
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1805
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1586
1806
{
1587
1807
  char buff[MAX_FIELD_NAME],*buff_end;
1588
1808
 
1600
1820
  for (uint32_t i=2 ; i< 100; i++)
1601
1821
  {
1602
1822
    *buff_end= '_';
1603
 
    internal::int10_to_str(i, buff_end+1, 10);
 
1823
    int10_to_str(i, buff_end+1, 10);
1604
1824
    if (!check_if_keyname_exists(buff,start,end))
1605
 
      return memory::sql_strdup(buff);
 
1825
      return sql_strdup(buff);
1606
1826
  }
1607
1827
  return (char*) "not_specified";               // Should never happen
1608
1828
}
1616
1836
  Rename a table.
1617
1837
 
1618
1838
  SYNOPSIS
1619
 
    rename_table()
1620
 
      session
 
1839
    mysql_rename_table()
1621
1840
      base                      The plugin::StorageEngine handle.
1622
1841
      old_db                    The old database name.
1623
1842
      old_name                  The old table name.
1624
1843
      new_db                    The new database name.
1625
1844
      new_name                  The new table name.
 
1845
      flags                     flags for build_table_filename().
 
1846
                                FN_FROM_IS_TMP old_name is temporary.
 
1847
                                FN_TO_IS_TMP   new_name is temporary.
1626
1848
 
1627
1849
  RETURN
1628
1850
    false   OK
1630
1852
*/
1631
1853
 
1632
1854
bool
1633
 
rename_table(Session &session,
1634
 
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1855
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
 
1856
                   const char *old_name, const char *new_db,
 
1857
                   const char *new_name, uint32_t flags)
1637
1858
{
 
1859
  Session *session= current_session;
 
1860
  char from[FN_REFLEN], to[FN_REFLEN];
 
1861
  char *from_base= from, *to_base= to;
1638
1862
  int error= 0;
1639
1863
 
1640
1864
  assert(base);
1641
1865
 
1642
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
1866
  build_table_filename(from, sizeof(from), old_db, old_name,
 
1867
                       flags & FN_FROM_IS_TMP);
 
1868
  build_table_filename(to, sizeof(to), new_db, new_name,
 
1869
                       flags & FN_TO_IS_TMP);
 
1870
 
 
1871
  if (!(error= base->renameTable(session, from_base, to_base)))
1643
1872
  {
1644
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1645
 
    return true;
 
1873
    if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1874
       && rename_table_proto_file(from_base, to_base))
 
1875
    {
 
1876
      error= errno;
 
1877
      base->renameTable(session, to_base, from_base);
 
1878
    }
1646
1879
  }
1647
1880
 
1648
 
  error= base->renameTable(session, from, to);
1649
 
 
1650
1881
  if (error == HA_ERR_WRONG_COMMAND)
1651
 
  {
1652
1882
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1653
 
  }
1654
1883
  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; 
 
1884
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
1885
  return(error != 0);
1669
1886
}
1670
1887
 
1671
1888
 
1684
1901
   the table is closed.
1685
1902
 
1686
1903
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
1904
    Lock on LOCK_open
1688
1905
    Win32 clients must also have a WRITE LOCK on the table !
1689
1906
*/
1690
1907
 
1692
1909
                              enum ha_extra_function function)
1693
1910
{
1694
1911
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1912
  safe_mutex_assert_owner(&LOCK_open);
1696
1913
 
1697
1914
  table->cursor->extra(function);
1698
1915
  /* Mark all tables that are in use as 'old' */
1699
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1916
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1700
1917
 
1701
1918
  /* 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);
 
1919
  remove_table_from_cache(session, table->s->db.str,
 
1920
                          table->s->table_name.str,
 
1921
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1922
}
1705
1923
 
1706
1924
/*
1716
1934
    reopen the table.
1717
1935
 
1718
1936
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
1937
    Lock on LOCK_open
1720
1938
    Win32 clients must also have a WRITE LOCK on the table !
1721
1939
*/
1722
1940
 
1727
1945
  /* Close lock if this is not got with LOCK TABLES */
1728
1946
  if (lock)
1729
1947
  {
1730
 
    unlockTables(lock);
 
1948
    mysql_unlock_tables(this, lock);
1731
1949
    lock= NULL;                 // Start locked threads
1732
1950
  }
1733
1951
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
1952
  unlink_open_table(table);
1735
1953
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1737
 
  locking::broadcast_refresh();
 
1954
  /* When lock on LOCK_open is freed other threads can continue */
 
1955
  broadcast_refresh();
1738
1956
}
1739
1957
 
1740
1958
/*
1743
1961
    true  Message should be sent by caller
1744
1962
          (admin operation or network communication failed)
1745
1963
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
1964
static bool mysql_admin_table(Session* session, TableList* tables,
1747
1965
                              HA_CHECK_OPT* check_opt,
1748
1966
                              const char *operator_name,
1749
1967
                              thr_lock_type lock_type,
1757
1975
  Item *item;
1758
1976
  LEX *lex= session->lex;
1759
1977
  int result_code= 0;
1760
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1761
1978
  const CHARSET_INFO * const cs= system_charset_info;
1762
1979
 
1763
1980
  if (! session->endActiveTransaction())
1772
1989
  item->maybe_null = 1;
1773
1990
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
1991
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
1992
  if (session->client->sendFields(&field_list))
1776
1993
    return true;
1777
1994
 
1778
1995
  for (table= tables; table; table= table->next_local)
1779
1996
  {
1780
1997
    char table_name[NAME_LEN*2+2];
 
1998
    char* db = table->db;
1781
1999
    bool fatal_error=0;
1782
2000
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
2001
    sprintf(table_name,"%s.%s",db,table->table_name);
1784
2002
    table->lock_type= lock_type;
1785
2003
    /* open only one table from local list of command */
1786
2004
    {
1793
2011
      /*
1794
2012
        Time zone tables and SP tables can be add to lex->query_tables list,
1795
2013
        so it have to be prepared.
1796
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2014
        TODO: Investigate if we can put extra tables into argument instead of
 
2015
        using lex->query_tables
1797
2016
      */
1798
2017
      lex->query_tables= table;
1799
2018
      lex->query_tables_last= &table->next_global;
1827
2046
    {
1828
2047
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
2048
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
2049
      session->client->store(table_name);
 
2050
      session->client->store(operator_name);
 
2051
      session->client->store(STRING_WITH_LEN("error"));
1833
2052
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
2053
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
2054
      session->client->store(buff, length);
 
2055
      ha_autocommit_or_rollback(session, 0);
1837
2056
      session->endTransaction(COMMIT);
1838
2057
      session->close_thread_tables();
1839
2058
      lex->reset_query_tables_list(false);
1840
2059
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
2060
      if (session->client->flush())
1842
2061
        goto err;
1843
2062
      continue;
1844
2063
    }
1845
2064
 
1846
2065
    /* Close all instances of the table to allow repair to rename files */
1847
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2066
    if (lock_type == TL_WRITE && table->table->s->version)
1848
2067
    {
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);
 
2068
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2069
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
2070
                                              "Waiting to get writelock");
 
2071
      mysql_lock_abort(session,table->table);
 
2072
      remove_table_from_cache(session, table->table->s->db.str,
 
2073
                              table->table->s->table_name.str,
 
2074
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2075
                              RTFC_CHECK_KILLED_FLAG);
1855
2076
      session->exit_cond(old_message);
1856
 
      if (session->getKilled())
 
2077
      if (session->killed)
1857
2078
        goto err;
1858
2079
      open_for_modify= 0;
1859
2080
    }
1869
2090
      DRIZZLE_ERROR *err;
1870
2091
      while ((err= it++))
1871
2092
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
2093
        session->client->store(table_name);
 
2094
        session->client->store(operator_name);
 
2095
        session->client->store(warning_level_names[err->level].str,
1875
2096
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
2097
        session->client->store(err->msg);
 
2098
        if (session->client->flush())
1878
2099
          goto err;
1879
2100
      }
1880
2101
      drizzle_reset_errors(session, true);
1881
2102
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
2103
    session->client->store(table_name);
 
2104
    session->client->store(operator_name);
1884
2105
 
1885
2106
    switch (result_code) {
1886
2107
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
2109
        char buf[ERRMSGSIZE+20];
1889
2110
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
2111
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
2112
        session->client->store(STRING_WITH_LEN("note"));
 
2113
        session->client->store(buf, length);
1893
2114
      }
1894
2115
      break;
1895
2116
 
1896
2117
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
2118
      session->client->store(STRING_WITH_LEN("status"));
 
2119
      session->client->store(STRING_WITH_LEN("OK"));
1899
2120
      break;
1900
2121
 
1901
2122
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
2123
      session->client->store(STRING_WITH_LEN("status"));
 
2124
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
2125
      break;
1905
2126
 
1906
2127
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
2128
      session->client->store(STRING_WITH_LEN("status"));
 
2129
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
2130
      open_for_modify= false;
1910
2131
      break;
1911
2132
 
1912
2133
    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"));
 
2134
      session->client->store(STRING_WITH_LEN("status"));
 
2135
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
2136
      break;
1916
2137
 
1917
2138
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
2139
      session->client->store(STRING_WITH_LEN("error"));
 
2140
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
2141
      fatal_error=1;
1921
2142
      break;
1922
2143
 
1923
2144
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
2145
      session->client->store(STRING_WITH_LEN("error"));
 
2146
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1926
2147
      break;
1927
2148
 
1928
2149
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1931
2152
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
2153
                             _("Unknown - internal error %d during operation"),
1933
2154
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
2155
        session->client->store(STRING_WITH_LEN("error"));
 
2156
        session->client->store(buf, length);
1936
2157
        fatal_error=1;
1937
2158
        break;
1938
2159
      }
1940
2161
    if (table->table)
1941
2162
    {
1942
2163
      if (fatal_error)
1943
 
      {
1944
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1945
 
      }
 
2164
        table->table->s->version=0;               // Force close of table
1946
2165
      else if (open_for_modify)
1947
2166
      {
1948
 
        if (table->table->getShare()->getType())
1949
 
        {
 
2167
        if (table->table->s->tmp_table)
1950
2168
          table->table->cursor->info(HA_STATUS_CONST);
1951
 
        }
1952
2169
        else
1953
2170
        {
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);
 
2171
          pthread_mutex_lock(&LOCK_open);
 
2172
          remove_table_from_cache(session, table->table->s->db.str,
 
2173
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2174
          pthread_mutex_unlock(&LOCK_open);
1957
2175
        }
1958
2176
      }
1959
2177
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
2178
    ha_autocommit_or_rollback(session, 0);
1961
2179
    session->endTransaction(COMMIT);
1962
2180
    session->close_thread_tables();
1963
2181
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
2182
    if (session->client->flush())
1965
2183
      goto err;
1966
2184
  }
1967
2185
 
1969
2187
  return(false);
1970
2188
 
1971
2189
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
2190
  ha_autocommit_or_rollback(session, 1);
1973
2191
  session->endTransaction(ROLLBACK);
1974
2192
  session->close_thread_tables();                       // Shouldn't be needed
1975
2193
  if (table)
1977
2195
  return(true);
1978
2196
}
1979
2197
 
 
2198
/*
 
2199
  Create a table identical to the specified table
 
2200
 
 
2201
  SYNOPSIS
 
2202
    mysql_create_like_table()
 
2203
    session             Thread object
 
2204
    table       Table list element for target table
 
2205
    src_table   Table list element for source table
 
2206
    create_info Create info
 
2207
 
 
2208
  RETURN VALUES
 
2209
    false OK
 
2210
    true  error
 
2211
*/
 
2212
 
 
2213
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2214
                             drizzled::message::Table& create_table_proto,
 
2215
                             drizzled::plugin::StorageEngine *engine_arg,
 
2216
                             bool is_if_not_exists,
 
2217
                             bool is_engine_set)
 
2218
{
 
2219
  Table *name_lock= 0;
 
2220
  char src_path[FN_REFLEN];
 
2221
  char *db= table->db;
 
2222
  char *table_name= table->table_name;
 
2223
  int  err;
 
2224
  bool res= true;
 
2225
  uint32_t not_used;
 
2226
  message::Table src_proto;
 
2227
  bool lex_identified_temp_table=
 
2228
    (create_table_proto.type() == drizzled::message::Table::TEMPORARY);
 
2229
 
 
2230
  /*
 
2231
    By opening source table we guarantee that it exists and no concurrent
 
2232
    DDL operation will mess with it. Later we also take an exclusive
 
2233
    name-lock on target table name, which makes copying of .frm cursor,
 
2234
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2235
    against concurrent DML and DDL operations on target table.
 
2236
    Thus by holding both these "locks" we ensure that our statement is
 
2237
    properly isolated from all concurrent operations which matter.
 
2238
  */
 
2239
  if (session->open_tables_from_list(&src_table, &not_used))
 
2240
    return true;
 
2241
 
 
2242
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
 
2243
 
 
2244
 
 
2245
  TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ? TEMP_TABLE : NO_TMP_TABLE);
 
2246
 
 
2247
  /*
 
2248
    Check that destination tables does not exist. Note that its name
 
2249
    was already checked when it was added to the table list.
 
2250
  */
 
2251
  if (lex_identified_temp_table)
 
2252
  {
 
2253
    if (session->find_temporary_table(db, table_name))
 
2254
      goto table_exists;
 
2255
  }
 
2256
  else
 
2257
  {
 
2258
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
2259
      goto err;
 
2260
    if (! name_lock)
 
2261
      goto table_exists;
 
2262
 
 
2263
    if (plugin::StorageEngine::getTableDefinition(*session,
 
2264
                                                  destination_identifier) == EEXIST)
 
2265
      goto table_exists;
 
2266
  }
 
2267
 
1980
2268
  /*
1981
2269
    Create a new table by copying from source table
1982
2270
 
1983
2271
    Altough exclusive name-lock on target table protects us from concurrent
1984
2272
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2273
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
2274
    LOCK_open in order to provide minimal atomicity against operations which
1987
2275
    disregard name-locks, like I_S implementation, for example. This is a
1988
2276
    temporary and should not be copied. Instead we should fix our code to
1989
2277
    always honor name-locks.
1990
2278
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
2279
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2280
    during the call to plugin::StorageEngine::createTable().
1993
2281
    See bug #28614 for more info.
1994
2282
  */
1995
 
static bool create_table_wrapper(Session &session,
1996
 
                                 const message::Table& create_table_proto,
1997
 
                                 identifier::Table::const_reference destination_identifier,
1998
 
                                 identifier::Table::const_reference source_identifier,
1999
 
                                 bool is_engine_set)
2000
 
{
2001
 
  // We require an additional table message because during parsing we used
2002
 
  // a "new" message and it will not have all of the information that the
2003
 
  // source table message would have.
2004
 
  message::Table new_table_message;
2005
 
  drizzled::error_t error;
2006
 
 
2007
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2008
 
 
2009
 
  if (not source_table_message)
2010
 
  {
2011
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  new_table_message.CopyFrom(*source_table_message);
2016
 
 
2017
 
  if (destination_identifier.isTmp())
2018
 
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
2283
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2284
  {
 
2285
    int protoerr= EEXIST;
 
2286
 
 
2287
    /*
 
2288
     * If an engine was not specified and we are reading from an I_S table, then we need to toss an
 
2289
     * error. This should go away soon.
 
2290
     * @todo make this go away!
 
2291
     */
 
2292
    if (! is_engine_set)
 
2293
    {
 
2294
      string tab_name(src_path);
 
2295
      string i_s_prefix("./information_schema/");
 
2296
      if (tab_name.compare(0, i_s_prefix.length(), i_s_prefix) == 0)
 
2297
      {
 
2298
        pthread_mutex_unlock(&LOCK_open);
 
2299
        my_error(ER_ILLEGAL_HA_CREATE_OPTION,
 
2300
                 MYF(0),
 
2301
                 "INFORMATION_ENGINE",
 
2302
                 "TEMPORARY");
 
2303
        goto err;
 
2304
      }
 
2305
    }
 
2306
 
 
2307
    protoerr= plugin::StorageEngine::getTableDefinition(*session,
 
2308
                                                        src_path,
 
2309
                                                        db,
 
2310
                                                        table_name,
 
2311
                                                        false,
 
2312
                                                        &src_proto);
 
2313
 
 
2314
    message::Table new_proto(src_proto);
 
2315
 
 
2316
    if (lex_identified_temp_table)
 
2317
    {
 
2318
      new_proto.set_type(message::Table::TEMPORARY);
 
2319
    }
 
2320
    else
 
2321
    {
 
2322
      new_proto.set_type(message::Table::STANDARD);
 
2323
    }
 
2324
 
 
2325
    if (is_engine_set)
 
2326
    {
 
2327
      message::Table::StorageEngine *protoengine;
 
2328
 
 
2329
      protoengine= new_proto.mutable_engine();
 
2330
      protoengine->set_name(create_table_proto.engine().name());
 
2331
    }
 
2332
 
 
2333
    if (protoerr == EEXIST)
 
2334
    {
 
2335
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
 
2336
                                                                       new_proto.engine().name());
 
2337
 
 
2338
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2339
      {
 
2340
        string dst_proto_path(destination_identifier.getPath());
 
2341
        dst_proto_path.append(".dfe");
 
2342
 
 
2343
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
 
2344
      }
 
2345
      else
 
2346
      {
 
2347
        protoerr= 0;
 
2348
      }
 
2349
    }
 
2350
 
 
2351
    if (protoerr)
 
2352
    {
 
2353
      if (errno == ENOENT)
 
2354
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2355
      else
 
2356
        my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), errno);
 
2357
      pthread_mutex_unlock(&LOCK_open);
 
2358
      goto err;
 
2359
    }
 
2360
 
 
2361
    /*
 
2362
      As mysql_truncate don't work on a new table at this stage of
 
2363
      creation, instead create the table directly (for both normal
 
2364
      and temporary tables).
 
2365
    */
 
2366
    err= plugin::StorageEngine::createTable(*session,
 
2367
                                            destination_identifier,
 
2368
                                            true, new_proto);
 
2369
  }
 
2370
  pthread_mutex_unlock(&LOCK_open);
 
2371
 
 
2372
  if (lex_identified_temp_table)
 
2373
  {
 
2374
    if (err || !session->open_temporary_table(destination_identifier))
 
2375
    {
 
2376
      (void) session->rm_temporary_table(engine_arg, destination_identifier);
 
2377
      goto err;
 
2378
    }
 
2379
  }
 
2380
  else if (err)
 
2381
  {
 
2382
    TableIdentifier identifier(db, table_name, NO_TMP_TABLE);
 
2383
    quick_rm_table(*session, identifier);
 
2384
 
 
2385
    goto err;
 
2386
  }
 
2387
 
 
2388
  /*
 
2389
    We have to write the query before we unlock the tables.
 
2390
  */
 
2391
  {
 
2392
    /*
 
2393
       Since temporary tables are not replicated under row-based
 
2394
       replication, CREATE TABLE ... LIKE ... needs special
 
2395
       treatement.  We have four cases to consider, according to the
 
2396
       following decision table:
 
2397
 
 
2398
           ==== ========= ========= ==============================
 
2399
           Case    Target    Source Write to binary log
 
2400
           ==== ========= ========= ==============================
 
2401
           1       normal    normal Original statement
 
2402
           2       normal temporary Generated statement
 
2403
           3    temporary    normal Nothing
 
2404
           4    temporary temporary Nothing
 
2405
           ==== ========= ========= ==============================
 
2406
    */
 
2407
    if (! lex_identified_temp_table)
 
2408
    {
 
2409
      if (src_table->table->s->tmp_table)               // Case 2
 
2410
      {
 
2411
        char buf[2048];
 
2412
        String query(buf, sizeof(buf), system_charset_info);
 
2413
        query.length(0);  // Have to zero it since constructor doesn't
 
2414
 
 
2415
 
 
2416
        /*
 
2417
          Here we open the destination table, on which we already have
 
2418
          name-lock. This is needed for store_create_info() to work.
 
2419
          The table will be closed by unlink_open_table() at the end
 
2420
          of this function.
 
2421
        */
 
2422
        table->table= name_lock;
 
2423
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2424
        if (session->reopen_name_locked_table(table, false))
 
2425
        {
 
2426
          pthread_mutex_unlock(&LOCK_open);
 
2427
          goto err;
 
2428
        }
 
2429
        pthread_mutex_unlock(&LOCK_open);
 
2430
 
 
2431
        int result= store_create_info(table, &query, is_if_not_exists);
 
2432
 
 
2433
        assert(result == 0); // store_create_info() always return 0
 
2434
        write_bin_log(session, query.ptr(), query.length());
 
2435
      }
 
2436
      else                                      // Case 1
 
2437
        write_bin_log(session, session->query, session->query_length);
 
2438
    }
 
2439
  }
 
2440
 
 
2441
  res= false;
 
2442
  goto err;
 
2443
 
 
2444
table_exists:
 
2445
  if (is_if_not_exists)
 
2446
  {
 
2447
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2448
    snprintf(warn_buff, sizeof(warn_buff),
 
2449
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2450
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2451
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2452
    res= false;
2020
2453
  }
2021
2454
  else
2022
 
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
2024
 
  }
2025
 
 
2026
 
  if (is_engine_set)
2027
 
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2029
 
  }
2030
 
 
2031
 
  { // We now do a selective copy of elements on to the new table.
2032
 
    new_table_message.set_name(create_table_proto.name());
2033
 
    new_table_message.set_schema(create_table_proto.schema());
2034
 
    new_table_message.set_catalog(create_table_proto.catalog());
2035
 
  }
2036
 
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2039
 
  {
2040
 
    if (new_table_message.fk_constraint(j).has_name())
2041
 
    {
2042
 
      std::string name(new_table_message.name());
2043
 
      char number[20];
2044
 
 
2045
 
      name.append("_ibfk_");
2046
 
      snprintf(number, sizeof(number), "%d", j+1);
2047
 
      name.append(number);
2048
 
 
2049
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
 
      pfkey->set_name(name);
2051
 
    }
2052
 
  }
2053
 
 
2054
 
  /*
2055
 
    As mysql_truncate don't work on a new table at this stage of
2056
 
    creation, instead create the table directly (for both normal and temporary tables).
2057
 
  */
2058
 
  bool success= plugin::StorageEngine::createTable(session,
2059
 
                                                   destination_identifier,
2060
 
                                                   new_table_message);
2061
 
 
2062
 
  if (success && not destination_identifier.isTmp())
2063
 
  {
2064
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2065
 
    transaction_services.createTable(session, new_table_message);
2066
 
  }
2067
 
 
2068
 
  return success;
2069
 
}
2070
 
 
2071
 
/*
2072
 
  Create a table identical to the specified table
2073
 
 
2074
 
  SYNOPSIS
2075
 
    create_like_table()
2076
 
    session             Thread object
2077
 
    table       Table list element for target table
2078
 
    src_table   Table list element for source table
2079
 
    create_info Create info
2080
 
 
2081
 
  RETURN VALUES
2082
 
    false OK
2083
 
    true  error
2084
 
*/
2085
 
 
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)
2092
 
{
2093
 
  bool res= true;
2094
 
  bool table_exists= false;
2095
 
 
2096
 
  /*
2097
 
    Check that destination tables does not exist. Note that its name
2098
 
    was already checked when it was added to the table list.
2099
 
 
2100
 
    For temporary tables we don't aim to grab locks.
2101
 
  */
2102
 
  if (destination_identifier.isTmp())
2103
 
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
2105
 
    {
2106
 
      table_exists= true;
2107
 
    }
2108
 
    else
2109
 
    {
2110
 
      bool was_created= create_table_wrapper(*session,
2111
 
                                             create_table_proto,
2112
 
                                             destination_identifier,
2113
 
                                             source_identifier,
2114
 
                                             is_engine_set);
2115
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2116
 
      {
2117
 
        (void) session->rm_temporary_table(destination_identifier, true);
2118
 
      }
2119
 
      else if (not session->open_temporary_table(destination_identifier))
2120
 
      {
2121
 
        // We created, but we can't open... also, a hack.
2122
 
        (void) session->rm_temporary_table(destination_identifier, true);
2123
 
      }
2124
 
      else
2125
 
      {
2126
 
        res= false;
2127
 
      }
2128
 
    }
2129
 
  }
2130
 
  else // Standard table which will require locks.
2131
 
  {
2132
 
    Table *name_lock= 0;
2133
 
 
2134
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2135
 
    {
2136
 
      if (name_lock)
2137
 
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
 
        session->unlink_open_table(name_lock);
2140
 
      }
2141
 
 
2142
 
      return res;
2143
 
    }
2144
 
 
2145
 
    if (not name_lock)
2146
 
    {
2147
 
      table_exists= true;
2148
 
    }
2149
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2150
 
    {
2151
 
      table_exists= true;
2152
 
    }
2153
 
    else // Otherwise we create the table
2154
 
    {
2155
 
      bool was_created;
2156
 
      {
2157
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
 
                                          source_identifier, is_engine_set);
2160
 
      }
2161
 
 
2162
 
      // So we blew the creation of the table, and we scramble to clean up
2163
 
      // anything that might have been created (read... it is a hack)
2164
 
      if (not was_created)
2165
 
      {
2166
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2167
 
      } 
2168
 
      else
2169
 
      {
2170
 
        res= false;
2171
 
      }
2172
 
    }
2173
 
 
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)
 
2455
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2456
 
 
2457
err:
 
2458
  if (name_lock)
 
2459
  {
 
2460
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2461
    session->unlink_open_table(name_lock);
 
2462
    pthread_mutex_unlock(&LOCK_open);
 
2463
  }
 
2464
  return(res);
 
2465
}
 
2466
 
 
2467
 
 
2468
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
2469
{
2204
2470
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
2471
 
2206
 
  return(admin_table(session, tables, check_opt,
 
2472
  return(mysql_admin_table(session, tables, check_opt,
2207
2473
                                "analyze", lock_type, true,
2208
2474
                                &Cursor::ha_analyze));
2209
2475
}
2210
2476
 
2211
2477
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2478
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
2479
{
2214
2480
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
2481
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2482
  return(mysql_admin_table(session, tables, check_opt,
2217
2483
                                "check", lock_type,
2218
2484
                                false,
2219
2485
                                &Cursor::ha_check));
2220
2486
}
2221
2487
 
2222
 
} /* namespace drizzled */
 
2488
 
 
2489
bool mysql_checksum_table(Session *session, TableList *tables,
 
2490
                          HA_CHECK_OPT *)
 
2491
{
 
2492
  TableList *table;
 
2493
  List<Item> field_list;
 
2494
  Item *item;
 
2495
 
 
2496
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
2497
  item->maybe_null= 1;
 
2498
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
2499
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
2500
  item->maybe_null= 1;
 
2501
  if (session->client->sendFields(&field_list))
 
2502
    return true;
 
2503
 
 
2504
  /* Open one table after the other to keep lock time as short as possible. */
 
2505
  for (table= tables; table; table= table->next_local)
 
2506
  {
 
2507
    char table_name[NAME_LEN*2+2];
 
2508
    Table *t;
 
2509
 
 
2510
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2511
 
 
2512
    t= table->table= session->openTableLock(table, TL_READ);
 
2513
    session->clear_error();                     // these errors shouldn't get client
 
2514
 
 
2515
    session->client->store(table_name);
 
2516
 
 
2517
    if (!t)
 
2518
    {
 
2519
      /* Table didn't exist */
 
2520
      session->client->store();
 
2521
      session->clear_error();
 
2522
    }
 
2523
    else
 
2524
    {
 
2525
      /**
 
2526
        @note if the engine keeps a checksum then we return the checksum, otherwise we calculate
 
2527
      */
 
2528
      if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
 
2529
      {
 
2530
        session->client->store((uint64_t)t->cursor->checksum());
 
2531
      }
 
2532
      else
 
2533
      {
 
2534
        /* calculating table's checksum */
 
2535
        ha_checksum crc= 0;
 
2536
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2537
 
 
2538
        t->use_all_columns();
 
2539
 
 
2540
        if (t->cursor->ha_rnd_init(1))
 
2541
          session->client->store();
 
2542
        else
 
2543
        {
 
2544
          for (;;)
 
2545
          {
 
2546
            ha_checksum row_crc= 0;
 
2547
            int error= t->cursor->rnd_next(t->record[0]);
 
2548
            if (unlikely(error))
 
2549
            {
 
2550
              if (error == HA_ERR_RECORD_DELETED)
 
2551
                continue;
 
2552
              break;
 
2553
            }
 
2554
            if (t->s->null_bytes)
 
2555
            {
 
2556
              /* fix undefined null bits */
 
2557
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
2558
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
2559
                t->record[0][0] |= 1;
 
2560
 
 
2561
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
2562
            }
 
2563
 
 
2564
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
2565
            {
 
2566
              Field *f= t->field[i];
 
2567
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
2568
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
2569
              {
 
2570
                String tmp;
 
2571
                f->val_str(&tmp);
 
2572
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
2573
              }
 
2574
              else
 
2575
                row_crc= my_checksum(row_crc, f->ptr,
 
2576
                                     f->pack_length());
 
2577
            }
 
2578
 
 
2579
            crc+= row_crc;
 
2580
          }
 
2581
          session->client->store((uint64_t)crc);
 
2582
          t->cursor->ha_rnd_end();
 
2583
        }
 
2584
      }
 
2585
      session->clear_error();
 
2586
      session->close_thread_tables();
 
2587
      table->table=0;                           // For query cache
 
2588
    }
 
2589
    if (session->client->flush())
 
2590
      goto err;
 
2591
  }
 
2592
 
 
2593
  session->my_eof();
 
2594
  return(false);
 
2595
 
 
2596
 err:
 
2597
  session->close_thread_tables();                       // Shouldn't be needed
 
2598
  if (table)
 
2599
    table->table=0;
 
2600
  return(true);
 
2601
}