~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2010-03-11 18:27:20 UTC
  • mfrom: (1333 staging)
  • mto: This revision was merged to the branch mainline in revision 1348.
  • Revision ID: mordred@inaugust.com-20100311182720-hd1h87y6cb1b1mp0
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
 
44
44
 
45
45
#include "drizzled/statement/alter_table.h"
46
 
#include "drizzled/plugin/info_schema_table.h"
47
46
#include "drizzled/sql_table.h"
48
47
#include "drizzled/pthread_globals.h"
49
48
 
55
54
namespace drizzled
56
55
{
57
56
 
 
57
extern plugin::StorageEngine *myisam_engine;
58
58
extern pid_t current_pid;
59
59
 
60
 
static const char hexchars[]= "0123456789abcdef";
61
60
bool is_primary_key(KEY *key_info)
62
61
{
63
62
  static const char * primary_key_name="PRIMARY";
86
85
    apply it to the table.
87
86
  */
88
87
  if (create_info->default_table_charset == NULL)
89
 
    create_info->default_table_charset= get_default_db_collation(db);
90
 
}
91
 
 
92
 
/*
93
 
  Translate a cursor name to a table name (WL #1324).
94
 
 
95
 
  SYNOPSIS
96
 
    filename_to_tablename()
97
 
      from                      The cursor name
98
 
      to                OUT     The table name
99
 
      to_length                 The size of the table name buffer.
100
 
 
101
 
  RETURN
102
 
    Table name length.
103
 
*/
104
 
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
105
 
{
106
 
  uint32_t length= 0;
107
 
 
108
 
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
109
 
  {
110
 
    /* Temporary table name. */
111
 
    length= strlen(strncpy(to, from, to_length));
112
 
  }
113
 
  else
114
 
  {
115
 
    for (; *from  && length < to_length; length++, from++)
116
 
    {
117
 
      if (*from != '@')
118
 
      {
119
 
        to[length]= *from;
120
 
        continue;
121
 
      }
122
 
      /* We've found an escaped char - skip the @ */
123
 
      from++;
124
 
      to[length]= 0;
125
 
      /* There will be a two-position hex-char version of the char */
126
 
      for (int x=1; x >= 0; x--)
127
 
      {
128
 
        if (*from >= '0' && *from <= '9')
129
 
          to[length] += ((*from++ - '0') << (4 * x));
130
 
        else if (*from >= 'a' && *from <= 'f')
131
 
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
132
 
      }
133
 
      /* Backup because we advanced extra in the inner loop */
134
 
      from--;
135
 
    } 
136
 
  }
137
 
 
138
 
  return length;
139
 
}
140
 
 
141
 
 
142
 
/*
143
 
  Translate a table name to a cursor name (WL #1324).
144
 
 
145
 
  SYNOPSIS
146
 
    tablename_to_filename()
147
 
      from                      The table name
148
 
      to                OUT     The cursor name
149
 
      to_length                 The size of the cursor name buffer.
150
 
 
151
 
  RETURN
152
 
    true if errors happen. false on success.
153
 
*/
154
 
bool tablename_to_filename(const char *from, char *to, size_t to_length)
155
 
{
156
 
  
157
 
  size_t length= 0;
158
 
  for (; *from  && length < to_length; length++, from++)
159
 
  {
160
 
    if ((*from >= '0' && *from <= '9') ||
161
 
        (*from >= 'A' && *from <= 'Z') ||
162
 
        (*from >= 'a' && *from <= 'z') ||
163
 
/* OSX defines an extra set of high-bit and multi-byte characters
164
 
   that cannot be used on the filesystem. Instead of trying to sort
165
 
   those out, we'll just escape encode all high-bit-set chars on OSX.
166
 
   It won't really hurt anything - it'll just make some filenames ugly. */
167
 
#if !defined(TARGET_OS_OSX)
168
 
        ((unsigned char)*from >= 128) ||
169
 
#endif
170
 
        (*from == '_') ||
171
 
        (*from == ' ') ||
172
 
        (*from == '-'))
173
 
    {
174
 
      to[length]= *from;
175
 
      continue;
176
 
    }
177
 
   
178
 
    if (length + 3 >= to_length)
179
 
      return true;
180
 
 
181
 
    /* We need to escape this char in a way that can be reversed */
182
 
    to[length++]= '@';
183
 
    to[length++]= hexchars[(*from >> 4) & 15];
184
 
    to[length]= hexchars[(*from) & 15];
185
 
  }
186
 
 
187
 
  if (internal::check_if_legal_tablename(to) &&
188
 
      length + 4 < to_length)
189
 
  {
190
 
    memcpy(to + length, "@@@", 4);
191
 
    length+= 3;
192
 
  }
193
 
  return false;
194
 
}
195
 
 
196
 
 
197
 
/*
198
 
  Creates path to a cursor: drizzle_data_dir/db/table.ext
199
 
 
200
 
  SYNOPSIS
201
 
   build_table_filename()
202
 
     buff                       Where to write result
203
 
                                This may be the same as table_name.
204
 
     bufflen                    buff size
205
 
     db                         Database name
206
 
     table_name                 Table name
207
 
     ext                        File extension.
208
 
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP
209
 
                                table_name is temporary, do not change.
210
 
 
211
 
  NOTES
212
 
 
213
 
    Uses database and table name, and extension to create
214
 
    a cursor name in drizzle_data_dir. Database and table
215
 
    names are converted from system_charset_info into "fscs".
216
 
    Unless flags indicate a temporary table name.
217
 
    'db' is always converted.
218
 
    'ext' is not converted.
219
 
 
220
 
    The conversion suppression is required for ALTER Table. This
221
 
    statement creates intermediate tables. These are regular
222
 
    (non-temporary) tables with a temporary name. Their path names must
223
 
    be derivable from the table name. So we cannot use
224
 
    build_tmptable_filename() for them.
225
 
 
226
 
  RETURN
227
 
    path length on success, 0 on failure
228
 
*/
229
 
 
230
 
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
231
 
{
232
 
  char dbbuff[FN_REFLEN];
233
 
  char tbbuff[FN_REFLEN];
234
 
  bool conversion_error= false;
235
 
 
236
 
  memset(tbbuff, 0, sizeof(tbbuff));
237
 
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
238
 
    strncpy(tbbuff, table_name, sizeof(tbbuff));
239
 
  else
240
 
  {
241
 
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
242
 
    if (conversion_error)
243
 
    {
244
 
      errmsg_printf(ERRMSG_LVL_ERROR,
245
 
                    _("Table name cannot be encoded and fit within filesystem "
246
 
                      "name length restrictions."));
247
 
      return 0;
248
 
    }
249
 
  }
250
 
  memset(dbbuff, 0, sizeof(dbbuff));
251
 
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
252
 
  if (conversion_error)
253
 
  {
254
 
    errmsg_printf(ERRMSG_LVL_ERROR,
255
 
                  _("Schema name cannot be encoded and fit within filesystem "
256
 
                    "name length restrictions."));
257
 
    return 0;
258
 
  }
259
 
   
260
 
 
261
 
  int rootdir_len= strlen(FN_ROOTDIR);
262
 
  string table_path(drizzle_data_home);
263
 
  int without_rootdir= table_path.length()-rootdir_len;
264
 
 
265
 
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
266
 
  if (without_rootdir >= 0)
267
 
  {
268
 
    const char *tmp= table_path.c_str()+without_rootdir;
269
 
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
270
 
      table_path.append(FN_ROOTDIR);
271
 
  }
272
 
 
273
 
  table_path.append(dbbuff);
274
 
  table_path.append(FN_ROOTDIR);
275
 
  table_path.append(tbbuff);
276
 
 
277
 
  if (bufflen < table_path.length())
278
 
    return 0;
279
 
 
280
 
  strcpy(buff, table_path.c_str());
281
 
 
282
 
  return table_path.length();
283
 
}
284
 
 
285
 
 
286
 
/*
287
 
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
288
 
 
289
 
  SYNOPSIS
290
 
   build_tmptable_filename()
291
 
     session                    The thread handle.
292
 
     buff                       Where to write result
293
 
     bufflen                    buff size
294
 
 
295
 
  NOTES
296
 
 
297
 
    Uses current_pid, thread_id, and tmp_table counter to create
298
 
    a cursor name in drizzle_tmpdir.
299
 
 
300
 
  RETURN
301
 
    path length on success, 0 on failure
302
 
*/
303
 
 
304
 
size_t build_tmptable_filename(char *buff, size_t bufflen)
305
 
{
306
 
  size_t length;
307
 
  ostringstream path_str, post_tmpdir_str;
308
 
  string tmp;
309
 
 
310
 
  Session *session= current_session;
311
 
 
312
 
  path_str << drizzle_tmpdir;
313
 
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
314
 
  post_tmpdir_str << session->thread_id << session->tmp_table++;
315
 
  tmp= post_tmpdir_str.str();
316
 
 
317
 
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
318
 
 
319
 
  path_str << tmp;
320
 
 
321
 
  if (bufflen < path_str.str().length())
322
 
    length= 0;
323
 
  else
324
 
    length= internal::unpack_filename(buff, path_str.str().c_str());
325
 
 
326
 
  return length;
 
88
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(db);
327
89
}
328
90
 
329
91
/*
342
104
*/
343
105
 
344
106
void write_bin_log(Session *session,
345
 
                   char const *query, size_t query_length)
 
107
                   char const *query)
346
108
{
347
109
  ReplicationServices &replication_services= ReplicationServices::singleton();
348
 
  replication_services.rawStatement(session, query, query_length);
 
110
  replication_services.rawStatement(session, query);
349
111
}
350
112
 
351
113
 
369
131
 
370
132
  built_query.append(table_name);
371
133
  built_query.append("`");
372
 
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
 
134
  replication_services.rawStatement(session, built_query);
373
135
}
374
136
 
375
137
/*
403
165
                         bool drop_temporary)
404
166
{
405
167
  TableList *table;
406
 
  char path[FN_REFLEN];
407
 
  uint32_t path_length= 0;
408
168
  String wrong_tables;
409
169
  int error= 0;
410
170
  bool foreign_key_error= false;
425
185
      table->db_type= share->db_type();
426
186
  }
427
187
 
428
 
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
188
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
429
189
  {
430
190
    pthread_mutex_unlock(&LOCK_open);
431
191
    return 1;
437
197
  for (table= tables; table; table= table->next_local)
438
198
  {
439
199
    char *db=table->db;
440
 
    plugin::StorageEngine *table_type;
441
200
 
442
201
    error= session->drop_temporary_table(table);
443
202
 
453
212
      error= 0;
454
213
    }
455
214
 
456
 
    table_type= table->db_type;
457
215
    if (drop_temporary == false)
458
216
    {
459
217
      Table *locked_table;
473
231
        error= -1;
474
232
        goto err_with_placeholders;
475
233
      }
476
 
      /* remove .frm cursor and engine files */
477
 
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
478
234
    }
479
 
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
 
235
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : STANDARD_TABLE);
480
236
 
481
 
    if (drop_temporary ||
482
 
        ((table_type == NULL
483
 
          && (plugin::StorageEngine::getTableDefinition(*session,
484
 
                                                        identifier) != EEXIST))))
 
237
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
485
238
    {
486
239
      // Table was not found on disk and table can't be created from engine
487
240
      if (if_exists)
493
246
    }
494
247
    else
495
248
    {
496
 
      error= plugin::StorageEngine::dropTable(*session,
497
 
                                              identifier,
498
 
                                              true);
 
249
      error= plugin::StorageEngine::dropTable(*session, identifier);
499
250
 
500
251
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
501
252
      {
502
 
        error= 0;
 
253
        error= 0;
503
254
        session->clear_error();
504
255
      }
505
256
 
511
262
    }
512
263
 
513
264
    if (error == 0 || (if_exists && foreign_key_error == false))
514
 
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
265
    {
 
266
      ReplicationServices &replication_services= ReplicationServices::singleton();
 
267
      replication_services.dropTable(session, string(db), string(table->table_name), if_exists);
 
268
    }
515
269
 
516
270
    if (error)
517
271
    {
565
319
bool quick_rm_table(Session& session,
566
320
                    TableIdentifier &identifier)
567
321
{
568
 
  return (plugin::StorageEngine::dropTable(session, identifier, false));
 
322
  return (plugin::StorageEngine::dropTable(session, identifier));
569
323
}
570
324
 
571
325
/*
775
529
  return 0;
776
530
}
777
531
 
778
 
int mysql_prepare_create_table(Session *session,
779
 
                               HA_CREATE_INFO *create_info,
780
 
                               message::Table *create_proto,
781
 
                               AlterInfo *alter_info,
782
 
                               bool tmp_table,
783
 
                               uint32_t *db_options,
784
 
                               Cursor *cursor,
785
 
                               KEY **key_info_buffer,
786
 
                               uint32_t *key_count,
787
 
                               int select_field_count)
 
532
static int mysql_prepare_create_table(Session *session,
 
533
                                      HA_CREATE_INFO *create_info,
 
534
                                      message::Table &create_proto,
 
535
                                      AlterInfo *alter_info,
 
536
                                      bool tmp_table,
 
537
                                      uint32_t *db_options,
 
538
                                      KEY **key_info_buffer,
 
539
                                      uint32_t *key_count,
 
540
                                      int select_field_count)
788
541
{
789
542
  const char    *key_name;
790
543
  CreateField   *sql_field,*dup_field;
799
552
  List_iterator<CreateField> it2(alter_info->create_list);
800
553
  uint32_t total_uneven_bit_length= 0;
801
554
 
 
555
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
 
556
 
802
557
  select_field_pos= alter_info->create_list.elements - select_field_count;
803
558
  null_fields=blob_columns=0;
804
 
  max_key_length= cursor->getEngine()->max_key_length();
 
559
  max_key_length= engine->max_key_length();
805
560
 
806
561
  for (field_no=0; (sql_field=it++) ; field_no++)
807
562
  {
1007
762
        }
1008
763
      }
1009
764
    }
1010
 
    /* Don't pack rows in old tables if the user has requested this */
1011
 
    if ((sql_field->flags & BLOB_FLAG) ||
1012
 
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
 
765
 
 
766
    /** @todo Get rid of this MyISAM-specific crap. */
 
767
    if (not create_proto.engine().name().compare("MyISAM") &&
 
768
        ((sql_field->flags & BLOB_FLAG) ||
 
769
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED)))
1013
770
      (*db_options)|= HA_OPTION_PACK_RECORD;
1014
771
    it2.rewind();
1015
772
  }
1042
799
    return(true);
1043
800
  }
1044
801
  if (auto_increment &&
1045
 
      (cursor->getEngine()->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
802
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
1046
803
  {
1047
804
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
1048
805
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
1049
806
    return(true);
1050
807
  }
1051
808
 
1052
 
  if (blob_columns && (cursor->getEngine()->check_flag(HTON_BIT_NO_BLOBS)))
 
809
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
1053
810
  {
1054
811
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
1055
812
               MYF(0));
1090
847
      continue;
1091
848
    }
1092
849
    (*key_count)++;
1093
 
    tmp=cursor->getEngine()->max_key_parts();
 
850
    tmp= engine->max_key_parts();
1094
851
    if (key->columns.elements > tmp)
1095
852
    {
1096
853
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
1139
896
      return(true);
1140
897
    }
1141
898
  }
1142
 
  tmp=cursor->getEngine()->max_keys();
 
899
  tmp= engine->max_keys();
1143
900
  if (*key_count > tmp)
1144
901
  {
1145
902
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
1194
951
    */
1195
952
    key_info->block_size= (key->key_create_info.block_size ?
1196
953
                           key->key_create_info.block_size :
1197
 
                           create_proto->options().key_block_size());
 
954
                           create_proto.options().key_block_size());
1198
955
 
1199
956
    if (key_info->block_size)
1200
957
      key_info->flags|= HA_USES_BLOCK_SIZE;
1254
1011
      }
1255
1012
      cols2.rewind();
1256
1013
 
1257
 
      if (create_proto->field_size() > 0)
1258
 
        protofield= create_proto->mutable_field(proto_field_nr - 1);
 
1014
      if (create_proto.field_size() > 0)
 
1015
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1259
1016
 
1260
1017
      {
1261
1018
        column->length*= sql_field->charset->mbmaxlen;
1262
1019
 
1263
1020
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1264
1021
        {
1265
 
          if (! (cursor->getEngine()->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
 
1022
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1266
1023
          {
1267
1024
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1268
1025
            return true;
1292
1049
          else
1293
1050
          {
1294
1051
            key_info->flags|= HA_NULL_PART_KEY;
1295
 
            if (! (cursor->getEngine()->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1052
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
1296
1053
            {
1297
1054
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1298
1055
              return true;
1301
1058
        }
1302
1059
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1303
1060
        {
1304
 
          if (column_nr == 0 || (cursor->getEngine()->check_flag(HTON_BIT_AUTO_PART_KEY)))
 
1061
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1305
1062
            auto_increment--;                   // Field is used
1306
1063
        }
1307
1064
      }
1316
1073
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1317
1074
        {
1318
1075
          if ((length=column->length) > max_key_length ||
1319
 
              length > cursor->getEngine()->max_key_part_length())
 
1076
              length > engine->max_key_part_length())
1320
1077
          {
1321
 
            length= min(max_key_length, cursor->getEngine()->max_key_part_length());
 
1078
            length= min(max_key_length, engine->max_key_part_length());
1322
1079
            if (key->type == Key::MULTIPLE)
1323
1080
            {
1324
1081
              /* not a critical problem */
1343
1100
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1344
1101
          return(true);
1345
1102
        }
1346
 
        else if (! (cursor->getEngine()->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
 
1103
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1347
1104
        {
1348
1105
          length=column->length;
1349
1106
        }
1353
1110
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1354
1111
          return(true);
1355
1112
      }
1356
 
      if (length > cursor->getEngine()->max_key_part_length())
 
1113
      if (length > engine->max_key_part_length())
1357
1114
      {
1358
 
        length= cursor->getEngine()->max_key_part_length();
 
1115
        length= engine->max_key_part_length();
1359
1116
        if (key->type == Key::MULTIPLE)
1360
1117
        {
1361
1118
          /* not a critical problem */
1435
1192
    key_info++;
1436
1193
  }
1437
1194
  if (!unique_key && !primary_key &&
1438
 
      (cursor->getEngine()->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1195
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1439
1196
  {
1440
1197
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1441
1198
    return(true);
1554
1311
bool mysql_create_table_no_lock(Session *session,
1555
1312
                                TableIdentifier &identifier,
1556
1313
                                HA_CREATE_INFO *create_info,
1557
 
                                message::Table *table_proto,
 
1314
                                message::Table &table_proto,
1558
1315
                                AlterInfo *alter_info,
1559
1316
                                bool internal_tmp_table,
1560
1317
                                uint32_t select_field_count,
1562
1319
{
1563
1320
  uint          db_options, key_count;
1564
1321
  KEY           *key_info_buffer;
1565
 
  Cursor        *cursor;
1566
1322
  bool          error= true;
1567
1323
  TableShare share;
1568
1324
  bool lex_identified_temp_table=
1569
 
    (table_proto->type() == message::Table::TEMPORARY);
 
1325
    (table_proto.type() == message::Table::TEMPORARY);
1570
1326
 
1571
1327
  /* Check for duplicate fields and check type of table to create */
1572
 
  if (!alter_info->create_list.elements)
 
1328
  if (not alter_info->create_list.elements)
1573
1329
  {
1574
1330
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1575
1331
               MYF(0));
1576
1332
    return true;
1577
1333
  }
1578
 
  assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
 
1334
  assert(strcmp(identifier.getTableName(), table_proto.name().c_str())==0);
1579
1335
  db_options= create_info->table_options;
 
1336
 
1580
1337
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
1581
1338
    db_options|=HA_OPTION_PACK_RECORD;
1582
 
  if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1583
 
  {
1584
 
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1585
 
    return true;
1586
 
  }
1587
1339
 
1588
1340
  set_table_default_charset(create_info, identifier.getDBName());
1589
1341
 
1590
1342
  /* Check if table exists */
1591
1343
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1592
1344
                                 internal_tmp_table,
1593
 
                                 &db_options, cursor,
 
1345
                                 &db_options,
1594
1346
                                 &key_info_buffer, &key_count,
1595
1347
                                 select_field_count))
1596
1348
    goto err;
1613
1365
  }
1614
1366
 
1615
1367
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1616
 
  if (!internal_tmp_table && ! lex_identified_temp_table)
 
1368
  if (not internal_tmp_table && not lex_identified_temp_table)
1617
1369
  {
1618
 
    if (plugin::StorageEngine::getTableDefinition(*session,
1619
 
                                                  identifier)==EEXIST)
 
1370
    if (plugin::StorageEngine::doesTableExist(*session,
 
1371
                                              identifier, false)==EEXIST)
1620
1372
    {
1621
1373
      if (is_if_not_exists)
1622
1374
      {
1627
1379
        create_info->table_existed= 1;          // Mark that table existed
1628
1380
      }
1629
1381
      else 
 
1382
      {
1630
1383
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1384
      }
1631
1385
 
1632
1386
      goto unlock_and_end;
1633
1387
    }
1655
1409
    one else is attempting to discover the table. Since
1656
1410
    it's not on disk as a frm cursor, no one could be using it!
1657
1411
  */
1658
 
  if (! lex_identified_temp_table)
 
1412
  if (not lex_identified_temp_table)
1659
1413
  {
1660
 
    int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
 
1414
    bool exists= plugin::StorageEngine::doesTableExist(*session, identifier, false);
1661
1415
 
1662
 
    switch (retcode)
 
1416
    if (exists)
1663
1417
    {
1664
 
      case ENOENT:
1665
 
        /* Normal case, no table exists. we can go and create it */
1666
 
        break;
1667
 
      case EEXIST:
1668
 
        if (is_if_not_exists)
1669
 
        {
1670
 
          error= false;
1671
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1672
 
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1673
 
                              identifier.getTableName());
1674
 
          create_info->table_existed= 1;                // Mark that table existed
1675
 
          goto unlock_and_end;
1676
 
        }
1677
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1678
 
        goto unlock_and_end;
1679
 
      default:
1680
 
        my_error(retcode, MYF(0), identifier.getTableName());
1681
 
        goto unlock_and_end;
 
1418
      if (is_if_not_exists)
 
1419
      {
 
1420
        error= false;
 
1421
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1422
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1423
                            identifier.getTableName());
 
1424
        create_info->table_existed= 1;          // Mark that table existed
 
1425
        goto unlock_and_end;
 
1426
      }
 
1427
 
 
1428
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1429
      goto unlock_and_end;
1682
1430
    }
1683
1431
  }
1684
1432
 
1691
1439
                       table_proto,
1692
1440
                       create_info, alter_info->create_list,
1693
1441
                       key_count, key_info_buffer))
 
1442
  {
1694
1443
    goto unlock_and_end;
 
1444
  }
1695
1445
 
1696
1446
  if (lex_identified_temp_table)
1697
1447
  {
1698
1448
    /* Open table and put in temporary table list */
1699
 
    if (!(session->open_temporary_table(identifier)))
 
1449
    if (not (session->open_temporary_table(identifier)))
1700
1450
    {
1701
 
      (void) session->rm_temporary_table(create_info->db_type, identifier);
 
1451
      (void) session->rm_temporary_table(identifier);
1702
1452
      goto unlock_and_end;
1703
1453
    }
1704
1454
  }
1705
1455
 
1706
 
  /*
1707
 
    Don't write statement if:
1708
 
    - It is an internal temporary table,
1709
 
    - Row-based logging is used and it we are creating a temporary table, or
1710
 
    - The binary log is not open.
1711
 
    Otherwise, the statement shall be binlogged.
1712
 
   */
1713
 
  if (!internal_tmp_table && ! lex_identified_temp_table)
1714
 
    write_bin_log(session, session->query, session->query_length);
 
1456
  if (not internal_tmp_table && not lex_identified_temp_table)
 
1457
  {
 
1458
    ReplicationServices &replication_services= ReplicationServices::singleton();
 
1459
    replication_services.createTable(session, table_proto);
 
1460
  }
1715
1461
  error= false;
1716
1462
unlock_and_end:
1717
1463
  pthread_mutex_unlock(&LOCK_open);
1718
1464
 
1719
1465
err:
1720
1466
  session->set_proc_info("After create");
1721
 
  delete cursor;
 
1467
 
1722
1468
  return(error);
1723
1469
}
1724
1470
 
1730
1476
bool mysql_create_table(Session *session,
1731
1477
                        TableIdentifier &identifier,
1732
1478
                        HA_CREATE_INFO *create_info,
1733
 
                        message::Table *table_proto,
 
1479
                        message::Table &table_proto,
1734
1480
                        AlterInfo *alter_info,
1735
1481
                        bool internal_tmp_table,
1736
1482
                        uint32_t select_field_count,
1739
1485
  Table *name_lock= NULL;
1740
1486
  bool result;
1741
1487
  bool lex_identified_temp_table=
1742
 
    (table_proto->type() == message::Table::TEMPORARY);
 
1488
    (table_proto.type() == message::Table::TEMPORARY);
1743
1489
 
1744
 
  if (! lex_identified_temp_table)
 
1490
  if (not lex_identified_temp_table)
1745
1491
  {
1746
1492
    if (session->lock_table_name_if_not_cached(identifier.getDBName(),
1747
1493
                                               identifier.getTableName(),
2200
1946
}
2201
1947
 
2202
1948
/*
 
1949
  We have to write the query before we unlock the named table.
 
1950
 
 
1951
  Since temporary tables are not replicated under row-based
 
1952
  replication, CREATE TABLE ... LIKE ... needs special
 
1953
  treatement.  We have four cases to consider, according to the
 
1954
  following decision table:
 
1955
 
 
1956
  ==== ========= ========= ==============================
 
1957
  Case    Target    Source Write to binary log
 
1958
  ==== ========= ========= ==============================
 
1959
  1       normal    normal Original statement
 
1960
  2       normal temporary Generated statement
 
1961
  3    temporary    normal Nothing
 
1962
  4    temporary temporary Nothing
 
1963
  ==== ========= ========= ==============================
 
1964
*/
 
1965
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
 
1966
                                     bool is_src_table_tmp, bool is_if_not_exists)
 
1967
{
 
1968
  if (is_src_table_tmp)
 
1969
  {
 
1970
    char buf[2048];
 
1971
    String query(buf, sizeof(buf), system_charset_info);
 
1972
    query.length(0);  // Have to zero it since constructor doesn't
 
1973
 
 
1974
 
 
1975
    /*
 
1976
      Here we open the destination table, on which we already have
 
1977
      name-lock. This is needed for store_create_info() to work.
 
1978
      The table will be closed by unlink_open_table() at the end
 
1979
      of this function.
 
1980
    */
 
1981
    table->table= name_lock;
 
1982
    pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
1983
    if (session->reopen_name_locked_table(table, false))
 
1984
    {
 
1985
      pthread_mutex_unlock(&LOCK_open);
 
1986
      return false;
 
1987
    }
 
1988
    pthread_mutex_unlock(&LOCK_open);
 
1989
 
 
1990
    int result= store_create_info(table, &query, is_if_not_exists);
 
1991
 
 
1992
    assert(result == 0); // store_create_info() always return 0
 
1993
    write_bin_log(session, query.ptr());
 
1994
  }
 
1995
  else                                      // Case 1
 
1996
  {
 
1997
    write_bin_log(session, session->query.c_str());
 
1998
  }
 
1999
 
 
2000
  return true;
 
2001
}
 
2002
 
 
2003
  /*
 
2004
    Create a new table by copying from source table
 
2005
 
 
2006
    Altough exclusive name-lock on target table protects us from concurrent
 
2007
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2008
    to plugin::StorageEngine::createTable() in critical section protected by
 
2009
    LOCK_open in order to provide minimal atomicity against operations which
 
2010
    disregard name-locks, like I_S implementation, for example. This is a
 
2011
    temporary and should not be copied. Instead we should fix our code to
 
2012
    always honor name-locks.
 
2013
 
 
2014
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2015
    during the call to plugin::StorageEngine::createTable().
 
2016
    See bug #28614 for more info.
 
2017
  */
 
2018
static bool create_table_wrapper(Session &session, message::Table& create_table_proto,
 
2019
                                 TableIdentifier &destination_identifier,
 
2020
                                 TableIdentifier &src_table,
 
2021
                                 bool lex_identified_temp_table, bool is_engine_set)
 
2022
{
 
2023
  int protoerr= EEXIST;
 
2024
  message::Table new_proto;
 
2025
  message::Table src_proto;
 
2026
 
 
2027
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
2028
                                                      src_table,
 
2029
                                                      &src_proto);
 
2030
  new_proto.CopyFrom(src_proto);
 
2031
 
 
2032
  if (lex_identified_temp_table)
 
2033
  {
 
2034
    new_proto.set_type(message::Table::TEMPORARY);
 
2035
  }
 
2036
  else
 
2037
  {
 
2038
    new_proto.set_type(message::Table::STANDARD);
 
2039
  }
 
2040
 
 
2041
  if (is_engine_set)
 
2042
  {
 
2043
    message::Table::StorageEngine *protoengine;
 
2044
 
 
2045
    protoengine= new_proto.mutable_engine();
 
2046
    protoengine->set_name(create_table_proto.engine().name());
 
2047
  }
 
2048
 
 
2049
  if (protoerr && protoerr != EEXIST)
 
2050
  {
 
2051
    if (errno == ENOENT)
 
2052
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName());
 
2053
    else
 
2054
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), errno);
 
2055
 
 
2056
    return false;
 
2057
  }
 
2058
 
 
2059
  /*
 
2060
    As mysql_truncate don't work on a new table at this stage of
 
2061
    creation, instead create the table directly (for both normal
 
2062
    and temporary tables).
 
2063
  */
 
2064
  int err= plugin::StorageEngine::createTable(session,
 
2065
                                              destination_identifier,
 
2066
                                              true, new_proto);
 
2067
 
 
2068
  return err ? false : true;
 
2069
}
 
2070
 
 
2071
/*
2203
2072
  Create a table identical to the specified table
2204
2073
 
2205
2074
  SYNOPSIS
2216
2085
 
2217
2086
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2218
2087
                             message::Table& create_table_proto,
2219
 
                             plugin::StorageEngine *engine_arg,
2220
2088
                             bool is_if_not_exists,
2221
2089
                             bool is_engine_set)
2222
2090
{
2223
2091
  Table *name_lock= 0;
2224
 
  char src_path[FN_REFLEN];
2225
2092
  char *db= table->db;
2226
2093
  char *table_name= table->table_name;
2227
 
  int  err;
2228
2094
  bool res= true;
2229
2095
  uint32_t not_used;
2230
 
  message::Table src_proto;
2231
2096
  bool lex_identified_temp_table=
2232
2097
    (create_table_proto.type() == message::Table::TEMPORARY);
 
2098
  bool was_created;
2233
2099
 
2234
2100
  /*
2235
2101
    By opening source table we guarantee that it exists and no concurrent
2243
2109
  if (session->open_tables_from_list(&src_table, &not_used))
2244
2110
    return true;
2245
2111
 
2246
 
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2247
 
 
2248
 
 
2249
 
  TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ? TEMP_TABLE : NO_TMP_TABLE);
 
2112
  TableIdentifier destination_identifier(db, table_name,
 
2113
                                         lex_identified_temp_table ? TEMP_TABLE : STANDARD_TABLE);
 
2114
 
 
2115
  TableIdentifier src_identifier(src_table->table->s->db.str,
 
2116
                                 src_table->table->s->table_name.str, src_table->table->s->tmp_table);
 
2117
 
 
2118
 
2250
2119
 
2251
2120
  /*
2252
2121
    Check that destination tables does not exist. Note that its name
2253
2122
    was already checked when it was added to the table list.
2254
2123
  */
 
2124
  bool table_exists= false;
2255
2125
  if (lex_identified_temp_table)
2256
2126
  {
2257
2127
    if (session->find_temporary_table(db, table_name))
2258
 
      goto table_exists;
 
2128
    {
 
2129
      table_exists= true;
 
2130
    }
2259
2131
  }
2260
2132
  else
2261
2133
  {
2262
2134
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2263
 
      goto err;
2264
 
    if (! name_lock)
2265
 
      goto table_exists;
2266
 
 
2267
 
    if (plugin::StorageEngine::getTableDefinition(*session,
2268
 
                                                  destination_identifier) == EEXIST)
2269
 
      goto table_exists;
2270
 
  }
2271
 
 
2272
 
  /*
2273
 
    Create a new table by copying from source table
2274
 
 
2275
 
    Altough exclusive name-lock on target table protects us from concurrent
2276
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
2277
 
    to plugin::StorageEngine::createTable() in critical section protected by
2278
 
    LOCK_open in order to provide minimal atomicity against operations which
2279
 
    disregard name-locks, like I_S implementation, for example. This is a
2280
 
    temporary and should not be copied. Instead we should fix our code to
2281
 
    always honor name-locks.
2282
 
 
2283
 
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2284
 
    during the call to plugin::StorageEngine::createTable().
2285
 
    See bug #28614 for more info.
2286
 
  */
2287
 
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2288
 
  {
2289
 
    int protoerr= EEXIST;
2290
 
 
2291
 
    /*
2292
 
     * If an engine was not specified and we are reading from an I_S table, then we need to toss an
2293
 
     * error. This should go away soon.
2294
 
     * @todo make this go away!
2295
 
     */
2296
 
    if (! is_engine_set)
2297
 
    {
2298
 
      string tab_name(src_path);
2299
 
      string i_s_prefix("./information_schema/");
2300
 
      if (tab_name.compare(0, i_s_prefix.length(), i_s_prefix) == 0)
2301
 
      {
2302
 
        pthread_mutex_unlock(&LOCK_open);
2303
 
        my_error(ER_ILLEGAL_HA_CREATE_OPTION,
2304
 
                 MYF(0),
2305
 
                 "INFORMATION_ENGINE",
2306
 
                 "TEMPORARY");
2307
 
        goto err;
2308
 
      }
2309
 
    }
2310
 
 
2311
 
    protoerr= plugin::StorageEngine::getTableDefinition(*session,
2312
 
                                                        src_path,
2313
 
                                                        db,
2314
 
                                                        table_name,
2315
 
                                                        false,
2316
 
                                                        &src_proto);
2317
 
 
2318
 
    message::Table new_proto(src_proto);
2319
 
 
2320
 
    if (lex_identified_temp_table)
2321
 
    {
2322
 
      new_proto.set_type(message::Table::TEMPORARY);
2323
 
    }
2324
 
    else
2325
 
    {
2326
 
      new_proto.set_type(message::Table::STANDARD);
2327
 
    }
2328
 
 
2329
 
    if (is_engine_set)
2330
 
    {
2331
 
      message::Table::StorageEngine *protoengine;
2332
 
 
2333
 
      protoengine= new_proto.mutable_engine();
2334
 
      protoengine->set_name(create_table_proto.engine().name());
2335
 
    }
2336
 
 
2337
 
    if (protoerr == EEXIST)
2338
 
    {
2339
 
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
2340
 
                                                                       new_proto.engine().name());
2341
 
 
2342
 
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2343
 
      {
2344
 
        string dst_proto_path(destination_identifier.getPath());
2345
 
        dst_proto_path.append(".dfe");
2346
 
 
2347
 
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
2348
 
      }
2349
 
      else
2350
 
      {
2351
 
        protoerr= 0;
2352
 
      }
2353
 
    }
2354
 
 
2355
 
    if (protoerr)
2356
 
    {
2357
 
      if (errno == ENOENT)
2358
 
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
2359
 
      else
2360
 
        my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), errno);
2361
 
      pthread_mutex_unlock(&LOCK_open);
2362
 
      goto err;
2363
 
    }
2364
 
 
2365
 
    /*
2366
 
      As mysql_truncate don't work on a new table at this stage of
2367
 
      creation, instead create the table directly (for both normal
2368
 
      and temporary tables).
2369
 
    */
2370
 
    err= plugin::StorageEngine::createTable(*session,
2371
 
                                            destination_identifier,
2372
 
                                            true, new_proto);
2373
 
  }
2374
 
  pthread_mutex_unlock(&LOCK_open);
2375
 
 
2376
 
  if (lex_identified_temp_table)
2377
 
  {
2378
 
    if (err || !session->open_temporary_table(destination_identifier))
2379
 
    {
2380
 
      (void) session->rm_temporary_table(engine_arg, destination_identifier);
2381
 
      goto err;
2382
 
    }
2383
 
  }
2384
 
  else if (err)
2385
 
  {
2386
 
    TableIdentifier identifier(db, table_name, NO_TMP_TABLE);
2387
 
    quick_rm_table(*session, identifier);
2388
 
 
2389
 
    goto err;
2390
 
  }
2391
 
 
2392
 
  /*
2393
 
    We have to write the query before we unlock the tables.
2394
 
  */
2395
 
  {
2396
 
    /*
2397
 
       Since temporary tables are not replicated under row-based
2398
 
       replication, CREATE TABLE ... LIKE ... needs special
2399
 
       treatement.  We have four cases to consider, according to the
2400
 
       following decision table:
2401
 
 
2402
 
           ==== ========= ========= ==============================
2403
 
           Case    Target    Source Write to binary log
2404
 
           ==== ========= ========= ==============================
2405
 
           1       normal    normal Original statement
2406
 
           2       normal temporary Generated statement
2407
 
           3    temporary    normal Nothing
2408
 
           4    temporary temporary Nothing
2409
 
           ==== ========= ========= ==============================
2410
 
    */
2411
 
    if (! lex_identified_temp_table)
2412
 
    {
2413
 
      if (src_table->table->s->tmp_table)               // Case 2
2414
 
      {
2415
 
        char buf[2048];
2416
 
        String query(buf, sizeof(buf), system_charset_info);
2417
 
        query.length(0);  // Have to zero it since constructor doesn't
2418
 
 
2419
 
 
2420
 
        /*
2421
 
          Here we open the destination table, on which we already have
2422
 
          name-lock. This is needed for store_create_info() to work.
2423
 
          The table will be closed by unlink_open_table() at the end
2424
 
          of this function.
2425
 
        */
2426
 
        table->table= name_lock;
2427
 
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2428
 
        if (session->reopen_name_locked_table(table, false))
2429
 
        {
2430
 
          pthread_mutex_unlock(&LOCK_open);
2431
 
          goto err;
2432
 
        }
2433
 
        pthread_mutex_unlock(&LOCK_open);
2434
 
 
2435
 
        int result= store_create_info(table, &query, is_if_not_exists);
2436
 
 
2437
 
        assert(result == 0); // store_create_info() always return 0
2438
 
        write_bin_log(session, query.ptr(), query.length());
2439
 
      }
2440
 
      else                                      // Case 1
2441
 
        write_bin_log(session, session->query, session->query_length);
2442
 
    }
2443
 
  }
2444
 
 
2445
 
  res= false;
2446
 
  goto err;
2447
 
 
2448
 
table_exists:
2449
 
  if (is_if_not_exists)
2450
 
  {
2451
 
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
2452
 
    snprintf(warn_buff, sizeof(warn_buff),
2453
 
             ER(ER_TABLE_EXISTS_ERROR), table_name);
2454
 
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2455
 
                 ER_TABLE_EXISTS_ERROR,warn_buff);
2456
 
    res= false;
2457
 
  }
2458
 
  else
2459
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2460
 
 
2461
 
err:
 
2135
    {
 
2136
      if (name_lock)
 
2137
      {
 
2138
        pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2139
        session->unlink_open_table(name_lock);
 
2140
        pthread_mutex_unlock(&LOCK_open);
 
2141
      }
 
2142
 
 
2143
      return res;
 
2144
    }
 
2145
 
 
2146
    if (not name_lock)
 
2147
    {
 
2148
      table_exists= true;
 
2149
    }
 
2150
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
 
2151
    {
 
2152
      table_exists= true;
 
2153
    }
 
2154
  }
 
2155
 
 
2156
  if (table_exists)
 
2157
  {
 
2158
    if (is_if_not_exists)
 
2159
    {
 
2160
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2161
      snprintf(warn_buff, sizeof(warn_buff),
 
2162
               ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2163
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2164
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2165
      res= false;
 
2166
    }
 
2167
    else
 
2168
    {
 
2169
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2170
    }
 
2171
  }
 
2172
  else // Otherwise we create the table
 
2173
  {
 
2174
    pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2175
    was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2176
                                      src_identifier, lex_identified_temp_table, is_engine_set);
 
2177
    pthread_mutex_unlock(&LOCK_open);
 
2178
 
 
2179
    // So we blew the creation of the table, and we scramble to clean up
 
2180
    // anything that might have been created (read... it is a hack)
 
2181
    if (not was_created)
 
2182
    {
 
2183
      if (lex_identified_temp_table)
 
2184
      {
 
2185
        (void) session->rm_temporary_table(destination_identifier);
 
2186
      }
 
2187
      else
 
2188
      {
 
2189
        TableIdentifier identifier(db, table_name, STANDARD_TABLE);
 
2190
        quick_rm_table(*session, identifier);
 
2191
      }
 
2192
    } 
 
2193
    else if (lex_identified_temp_table && not session->open_temporary_table(destination_identifier))
 
2194
    {
 
2195
      // We created, but we can't open... also, a hack.
 
2196
      (void) session->rm_temporary_table(destination_identifier);
 
2197
    }
 
2198
    else
 
2199
    {
 
2200
      if (not lex_identified_temp_table)
 
2201
      {
 
2202
        bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
 
2203
        (void)rc;
 
2204
      }
 
2205
 
 
2206
      res= false;
 
2207
    }
 
2208
  }
 
2209
 
2462
2210
  if (name_lock)
2463
2211
  {
2464
2212
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2465
2213
    session->unlink_open_table(name_lock);
2466
2214
    pthread_mutex_unlock(&LOCK_open);
2467
2215
  }
 
2216
 
2468
2217
  return(res);
2469
2218
}
2470
2219