~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2010-03-15 21:50:05 UTC
  • mto: This revision was merged to the branch mainline in revision 1343.
  • Revision ID: brian@gaz-20100315215005-oqoblpbll9n0albj
Merge of table cache/def DD.

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>
 
35
#include <drizzled/replication_services.h>
36
36
#include "drizzled/transaction_services.h"
37
37
#include <drizzled/table_proto.h>
38
38
#include <drizzled/plugin/client.h>
39
 
#include <drizzled/identifier.h>
 
39
#include <drizzled/table_identifier.h>
40
40
#include "drizzled/internal/m_string.h"
41
41
#include "drizzled/global_charset_info.h"
42
42
#include "drizzled/charset.h"
43
43
 
44
 
#include "drizzled/definition/cache.h"
45
 
 
46
44
 
47
45
#include "drizzled/statement/alter_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
53
 
59
54
namespace drizzled
60
55
{
61
56
 
62
 
bool is_primary_key(KeyInfo *key_info)
 
57
extern plugin::StorageEngine *myisam_engine;
 
58
extern pid_t current_pid;
 
59
 
 
60
bool is_primary_key(KEY *key_info)
63
61
{
64
62
  static const char * primary_key_name="PRIMARY";
65
63
  return (strcmp(key_info->name, primary_key_name)==0);
74
72
    return NULL;
75
73
}
76
74
 
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);
 
75
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
76
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
79
77
 
80
78
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
79
 
86
84
    let's fetch the database default character set and
87
85
    apply it to the table.
88
86
  */
89
 
  identifier::Schema identifier(db);
90
87
  if (create_info->default_table_charset == NULL)
91
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
88
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(db);
92
89
}
93
90
 
94
91
/*
106
103
    cursor
107
104
*/
108
105
 
109
 
void write_bin_log(Session *session, const std::string &query)
110
 
{
111
 
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
 
106
void write_bin_log(Session *session,
 
107
                   char const *query)
 
108
{
 
109
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
110
  replication_services.rawStatement(session, query);
 
111
}
 
112
 
 
113
 
 
114
/* Should should be refactored to go away */
 
115
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
116
{
 
117
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
118
  string built_query;
 
119
 
 
120
  if (if_exists)
 
121
    built_query.append("DROP TABLE IF EXISTS ");
 
122
  else
 
123
    built_query.append("DROP TABLE ");
 
124
 
 
125
  built_query.append("`");
 
126
  if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
 
127
  {
 
128
    built_query.append(db_name);
 
129
    built_query.append("`.`");
 
130
  }
 
131
 
 
132
  built_query.append(table_name);
 
133
  built_query.append("`");
 
134
  replication_services.rawStatement(session, built_query);
113
135
}
114
136
 
115
137
/*
116
138
  Execute the drop of a normal or temporary table
117
139
 
118
140
  SYNOPSIS
119
 
    rm_table_part2()
 
141
    mysql_rm_table_part2()
120
142
    session                     Thread Cursor
121
143
    tables              Tables to drop
122
144
    if_exists           If set, don't give an error if table doesn't exists.
123
145
                        In this case we give an warning of level 'NOTE'
124
146
    drop_temporary      Only drop temporary tables
125
147
 
126
 
  @todo
 
148
  TODO:
127
149
    When logging to the binary log, we should log
128
150
    tmp_tables and transactional tables as separate statements if we
129
151
    are in a transaction;  This is needed to get these tables into the
139
161
   -1   Thread was killed
140
162
*/
141
163
 
142
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                   bool drop_temporary)
 
164
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
165
                         bool drop_temporary)
144
166
{
145
167
  TableList *table;
146
168
  String wrong_tables;
147
169
  int error= 0;
148
170
  bool foreign_key_error= false;
149
171
 
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:
 
172
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
173
 
 
174
  /*
 
175
    If we have the table in the definition cache, we don't have to check the
 
176
    .frm cursor to find if the table is a normal table (not view) and what
 
177
    engine to use.
 
178
  */
 
179
 
 
180
  for (table= tables; table; table= table->next_local)
 
181
  {
 
182
    TableShare *share;
 
183
    table->db_type= NULL;
 
184
    if ((share= TableShare::getShare(table->db, table->table_name)))
 
185
      table->db_type= share->db_type();
 
186
  }
 
187
 
 
188
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
189
  {
 
190
    pthread_mutex_unlock(&LOCK_open);
 
191
    return 1;
 
192
  }
 
193
 
 
194
  /* Don't give warnings for not found errors, as we already generate notes */
 
195
  session->no_warnings_for_error= 1;
 
196
 
 
197
  for (table= tables; table; table= table->next_local)
 
198
  {
 
199
    char *db=table->db;
 
200
 
 
201
    error= session->drop_temporary_table(table);
 
202
 
 
203
    switch (error) {
 
204
    case  0:
 
205
      // removed temporary table
 
206
      continue;
 
207
    case -1:
 
208
      error= 1;
 
209
      goto err_with_placeholders;
 
210
    default:
 
211
      // temporary table not found
 
212
      error= 0;
 
213
    }
 
214
 
 
215
    if (drop_temporary == false)
 
216
    {
 
217
      Table *locked_table;
 
218
      abort_locked_tables(session, db, table->table_name);
 
219
      remove_table_from_cache(session, db, table->table_name,
 
220
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
221
                              RTFC_CHECK_KILLED_FLAG);
 
222
      /*
 
223
        If the table was used in lock tables, remember it so that
 
224
        unlock_table_names can free it
 
225
      */
 
226
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
227
        table->table= locked_table;
 
228
 
 
229
      if (session->killed)
 
230
      {
 
231
        error= -1;
 
232
        goto err_with_placeholders;
 
233
      }
 
234
    }
 
235
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : STANDARD_TABLE);
 
236
 
 
237
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
238
    {
 
239
      // Table was not found on disk and table can't be created from engine
 
240
      if (if_exists)
 
241
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
242
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
243
                            table->table_name);
 
244
      else
173
245
        error= 1;
174
 
        break;
175
 
      default:
176
 
        // temporary table not found
 
246
    }
 
247
    else
 
248
    {
 
249
      error= plugin::StorageEngine::dropTable(*session, identifier);
 
250
 
 
251
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
252
      {
177
253
        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
 
 
 
254
        session->clear_error();
 
255
      }
 
256
 
 
257
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
258
      {
 
259
        /* the table is referenced by a foreign key constraint */
 
260
        foreign_key_error= true;
 
261
      }
 
262
    }
 
263
 
 
264
    if (error == 0 || (if_exists && foreign_key_error == false))
 
265
    {
 
266
      ReplicationServices &replication_services= ReplicationServices::singleton();
 
267
      replication_services.dropTable(session, string(db), string(table->table_name), if_exists);
 
268
    }
 
269
 
 
270
    if (error)
 
271
    {
 
272
      if (wrong_tables.length())
 
273
        wrong_tables.append(',');
 
274
      wrong_tables.append(String(table->table_name,system_charset_info));
 
275
    }
 
276
  }
 
277
  /*
 
278
    It's safe to unlock LOCK_open: we have an exclusive lock
 
279
    on the table name.
 
280
  */
 
281
  pthread_mutex_unlock(&LOCK_open);
 
282
  error= 0;
253
283
  if (wrong_tables.length())
254
284
  {
255
 
    if (not foreign_key_error)
256
 
    {
 
285
    if (!foreign_key_error)
257
286
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
287
                      wrong_tables.c_ptr());
259
 
    }
260
288
    else
261
289
    {
262
290
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
264
292
    error= 1;
265
293
  }
266
294
 
 
295
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
 
296
err_with_placeholders:
 
297
  unlock_table_names(tables, NULL);
 
298
  pthread_mutex_unlock(&LOCK_open);
267
299
  session->no_warnings_for_error= 0;
268
300
 
269
 
  return error;
 
301
  return(error);
 
302
}
 
303
 
 
304
 
 
305
/*
 
306
  Quickly remove a table.
 
307
 
 
308
  SYNOPSIS
 
309
    quick_rm_table()
 
310
      base                      The plugin::StorageEngine handle.
 
311
      db                        The database name.
 
312
      table_name                The table name.
 
313
      is_tmp                    If the table is temp.
 
314
 
 
315
  RETURN
 
316
    0           OK
 
317
    != 0        Error
 
318
*/
 
319
bool quick_rm_table(Session& session,
 
320
                    TableIdentifier &identifier)
 
321
{
 
322
  return (plugin::StorageEngine::dropTable(session, identifier));
270
323
}
271
324
 
272
325
/*
282
335
  PRIMARY keys are prioritized.
283
336
*/
284
337
 
285
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
338
static int sort_keys(KEY *a, KEY *b)
286
339
{
287
340
  ulong a_flags= a->flags, b_flags= b->flags;
288
341
 
334
387
    1             Error
335
388
*/
336
389
 
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
390
static bool check_duplicates_in_interval(const char *set_or_name,
372
391
                                         const char *name, TYPELIB *typelib,
373
392
                                         const CHARSET_INFO * const cs,
378
397
  unsigned int *cur_length= typelib->type_lengths;
379
398
  *dup_val_count= 0;
380
399
 
381
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
382
 
 
383
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
400
  for ( ; tmp.count > 1; cur_value++, cur_length++)
384
401
  {
385
402
    tmp.type_names++;
386
403
    tmp.type_lengths++;
387
404
    tmp.count--;
388
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
405
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
389
406
    {
390
407
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
408
               name,*cur_value,set_or_name);
392
409
      return 1;
393
410
    }
394
 
    else
395
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
396
411
  }
397
412
  return 0;
398
413
}
465
480
 
466
481
  switch (sql_field->sql_type) {
467
482
  case DRIZZLE_TYPE_BLOB:
 
483
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
468
484
    sql_field->length= 8; // Unireg field length
469
485
    (*blob_columns)++;
470
486
    break;
471
 
 
 
487
  case DRIZZLE_TYPE_VARCHAR:
 
488
    sql_field->pack_flag=0;
 
489
    break;
472
490
  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:
 
491
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
 
492
    if (check_duplicates_in_interval("ENUM",
 
493
                                     sql_field->field_name,
 
494
                                     sql_field->interval,
 
495
                                     sql_field->charset,
 
496
                                     &dup_val_count))
 
497
      return 1;
 
498
    break;
 
499
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
500
  case DRIZZLE_TYPE_DATETIME:
 
501
  case DRIZZLE_TYPE_NULL:
 
502
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
 
503
    break;
 
504
  case DRIZZLE_TYPE_DECIMAL:
 
505
    sql_field->pack_flag= 0;
 
506
    break;
486
507
  case DRIZZLE_TYPE_TIMESTAMP:
487
508
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
509
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
493
514
        (*timestamps_with_niladic)++;
494
515
      }
495
516
      else
496
 
      {
497
517
        sql_field->unireg_check= Field::NONE;
498
 
      }
499
518
    }
500
519
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
520
      (*timestamps_with_niladic)++;
503
 
    }
504
521
 
505
522
    (*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:
 
523
    /* fall-through */
 
524
  default:
 
525
    sql_field->pack_flag=(0 |
 
526
                          f_settype((uint32_t) sql_field->sql_type));
520
527
    break;
521
528
  }
522
 
 
523
529
  return 0;
524
530
}
525
531
 
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)
 
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)
535
541
{
536
542
  const char    *key_name;
537
543
  CreateField   *sql_field,*dup_field;
538
544
  uint          field,null_fields,blob_columns,max_key_length;
539
545
  ulong         record_offset= 0;
540
 
  KeyInfo               *key_info;
541
 
  KeyPartInfo *key_part_info;
 
546
  KEY           *key_info;
 
547
  KEY_PART_INFO *key_part_info;
542
548
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
549
  int           field_no,dup_no;
544
550
  int           select_field_pos,auto_increment=0;
545
551
  List_iterator<CreateField> it(alter_info->create_list);
546
552
  List_iterator<CreateField> it2(alter_info->create_list);
552
558
  null_fields=blob_columns=0;
553
559
  max_key_length= engine->max_key_length();
554
560
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
561
  for (field_no=0; (sql_field=it++) ; field_no++)
556
562
  {
557
563
    const CHARSET_INFO *save_cs;
558
564
 
562
568
      executing a prepared statement for the second time.
563
569
    */
564
570
    sql_field->length= sql_field->char_length;
565
 
 
566
571
    if (!sql_field->charset)
567
572
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
573
    /*
570
574
      table_charset is set in ALTER Table if we want change character set
571
575
      for all varchar/char columns.
618
622
 
619
623
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
624
    {
621
 
      size_t dummy;
 
625
      uint32_t dummy;
622
626
      const CHARSET_INFO * const cs= sql_field->charset;
623
627
      TYPELIB *interval= sql_field->interval;
624
628
 
651
655
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
656
                                       cs, &dummy))
653
657
          {
654
 
            size_t cnv_errs;
 
658
            uint32_t cnv_errs;
655
659
            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());
 
660
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
661
                                                  conv.length());
657
662
            interval->type_lengths[i]= conv.length();
658
663
          }
659
664
 
693
698
            }
694
699
          }
695
700
        }
696
 
        uint32_t new_dummy;
697
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
701
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
698
702
        sql_field->length= field_length;
699
703
      }
700
704
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
762
766
    /** @todo Get rid of this MyISAM-specific crap. */
763
767
    if (not create_proto.engine().name().compare("MyISAM") &&
764
768
        ((sql_field->flags & BLOB_FLAG) ||
765
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
766
 
    {
 
769
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED)))
767
770
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
771
    it2.rewind();
771
772
  }
772
773
 
833
834
      fk_key_count++;
834
835
      if (((Foreign_key *)key)->validate(alter_info->create_list))
835
836
        return true;
836
 
 
837
837
      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
838
      if (fk_key->ref_columns.elements &&
849
839
          fk_key->ref_columns.elements != fk_key->columns.elements)
850
840
      {
879
869
             key2->name.str != ignore_key &&
880
870
             !foreign_key_prefix(key, key2)))
881
871
        {
882
 
          /* @todo issue warning message */
 
872
          /* TODO: issue warning message */
883
873
          /* mark that the generated key should be ignored */
884
874
          if (!key2->generated ||
885
875
              (key->generated && key->columns.elements <
913
903
    return(true);
914
904
  }
915
905
 
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);
 
906
  (*key_info_buffer)= key_info= (KEY*) memory::sql_calloc(sizeof(KEY) * (*key_count));
 
907
  key_part_info=(KEY_PART_INFO*) memory::sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
918
908
  if (!*key_info_buffer || ! key_part_info)
919
909
    return(true);                               // Out of memory
920
910
 
954
944
    key_info->usable_key_parts= key_number;
955
945
    key_info->algorithm= key->key_create_info.algorithm;
956
946
 
 
947
    /* Take block size from key part or table part */
 
948
    /*
 
949
      TODO: Add warning if block size changes. We can't do it here, as
 
950
      this may depend on the size of the key
 
951
    */
 
952
    key_info->block_size= (key->key_create_info.block_size ?
 
953
                           key->key_create_info.block_size :
 
954
                           create_proto.options().key_block_size());
 
955
 
 
956
    if (key_info->block_size)
 
957
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
958
 
957
959
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
958
960
                                           key->key_create_info.comment.str,
959
961
                                           key->key_create_info.comment.str +
990
992
             my_strcasecmp(system_charset_info,
991
993
                           column->field_name.str,
992
994
                           sql_field->field_name))
993
 
      {
994
995
        field++;
995
 
      }
996
 
 
997
996
      if (!sql_field)
998
997
      {
999
998
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
999
        return(true);
1001
1000
      }
1002
 
 
1003
1001
      while ((dup_column= cols2++) != column)
1004
1002
      {
1005
1003
        if (!my_strcasecmp(system_charset_info,
1032
1030
            return true;
1033
1031
          }
1034
1032
        }
1035
 
 
1036
1033
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
1034
        {
1038
1035
          if (key->type == Key::PRIMARY)
1045
1042
            {
1046
1043
              message::Table::Field::FieldConstraints *constraints;
1047
1044
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
 
1045
              constraints->set_is_nullable(false);
1049
1046
            }
1050
1047
 
1051
1048
          }
1059
1056
            }
1060
1057
          }
1061
1058
        }
1062
 
 
1063
1059
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
1060
        {
1065
1061
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1069
1065
 
1070
1066
      key_part_info->fieldnr= field;
1071
1067
      key_part_info->offset=  (uint16_t) sql_field->offset;
1072
 
      key_part_info->key_type= 0;
 
1068
      key_part_info->key_type=sql_field->pack_flag;
1073
1069
      length= sql_field->key_length;
1074
1070
 
1075
1071
      if (column->length)
1137
1133
      key_part_info->length=(uint16_t) length;
1138
1134
      /* Use packed keys for long strings on the first column */
1139
1135
      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)))
 
1136
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1137
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1138
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1143
1139
      {
1144
1140
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1145
1141
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1146
 
        {
1147
1142
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1148
 
        }
1149
1143
        else
1150
 
        {
1151
1144
          key_info->flags|= HA_PACK_KEY;
1152
 
        }
1153
1145
      }
1154
1146
      /* Check if the key segment is partial, set the key flag accordingly */
1155
1147
      if (length != sql_field->key_length)
1184
1176
        key_info->name=(char*) key_name;
1185
1177
      }
1186
1178
    }
1187
 
 
1188
1179
    if (!key_info->name || check_column_name(key_info->name))
1189
1180
    {
1190
1181
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1182
      return(true);
1192
1183
    }
1193
 
 
1194
1184
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1185
      unique_key=1;
1197
 
    }
1198
 
 
1199
1186
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1187
    if (key_length > max_key_length)
1202
1188
    {
1203
1189
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1190
      return(true);
1205
1191
    }
1206
 
 
1207
1192
    key_info++;
1208
1193
  }
1209
 
 
1210
1194
  if (!unique_key && !primary_key &&
1211
1195
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1212
1196
  {
1213
1197
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1198
    return(true);
1215
1199
  }
1216
 
 
1217
1200
  if (auto_increment > 0)
1218
1201
  {
1219
1202
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1220
1203
    return(true);
1221
1204
  }
1222
1205
  /* Sort keys in optimized order */
1223
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
 
1206
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1224
1207
                     (qsort_cmp) sort_keys);
1225
1208
 
1226
1209
  /* Check fields. */
1294
1277
  return 0;
1295
1278
}
1296
1279
 
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
1280
 
1399
1281
/*
1400
1282
  Ignore the name of this function... it locks :(
1402
1284
  Create a table
1403
1285
 
1404
1286
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1287
    mysql_create_table_no_lock()
1406
1288
    session                     Thread object
1407
1289
    db                  Database
1408
1290
    table_name          Table name
1418
1300
 
1419
1301
    Note that this function assumes that caller already have taken
1420
1302
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1303
    that concurrent operations won't intervene. mysql_create_table()
1422
1304
    is a wrapper that can be used for this.
1423
1305
 
1424
1306
  RETURN VALUES
1426
1308
    true  error
1427
1309
*/
1428
1310
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1311
bool mysql_create_table_no_lock(Session *session,
 
1312
                                TableIdentifier &identifier,
1431
1313
                                HA_CREATE_INFO *create_info,
1432
1314
                                message::Table &table_proto,
1433
1315
                                AlterInfo *alter_info,
1436
1318
                                bool is_if_not_exists)
1437
1319
{
1438
1320
  uint          db_options, key_count;
1439
 
  KeyInfo               *key_info_buffer;
 
1321
  KEY           *key_info_buffer;
1440
1322
  bool          error= true;
 
1323
  TableShare share;
 
1324
  bool lex_identified_temp_table=
 
1325
    (table_proto.type() == message::Table::TEMPORARY);
1441
1326
 
1442
1327
  /* Check for duplicate fields and check type of table to create */
1443
1328
  if (not alter_info->create_list.elements)
1446
1331
               MYF(0));
1447
1332
    return true;
1448
1333
  }
1449
 
  assert(identifier.getTableName() == table_proto.name());
 
1334
  assert(strcmp(identifier.getTableName(), table_proto.name().c_str())==0);
1450
1335
  db_options= create_info->table_options;
1451
1336
 
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)
 
1337
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1338
    db_options|=HA_OPTION_PACK_RECORD;
 
1339
 
 
1340
  set_table_default_charset(create_info, identifier.getDBName());
 
1341
 
 
1342
  /* Check if table exists */
 
1343
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1344
                                 internal_tmp_table,
 
1345
                                 &db_options,
 
1346
                                 &key_info_buffer, &key_count,
 
1347
                                 select_field_count))
 
1348
    goto err;
 
1349
 
 
1350
  /* Check if table already exists */
 
1351
  if (lex_identified_temp_table &&
 
1352
      session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1498
1353
  {
1499
1354
    if (is_if_not_exists)
1500
1355
    {
 
1356
      create_info->table_existed= 1;            // Mark that table existed
1501
1357
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
1358
                          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);
 
1359
                          identifier.getTableName());
 
1360
      error= 0;
 
1361
      goto err;
 
1362
    }
 
1363
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1364
    goto err;
 
1365
  }
 
1366
 
 
1367
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1368
  if (not internal_tmp_table && not lex_identified_temp_table)
 
1369
  {
 
1370
    if (plugin::StorageEngine::doesTableExist(*session,
 
1371
                                              identifier, false)==EEXIST)
 
1372
    {
 
1373
      if (is_if_not_exists)
 
1374
      {
 
1375
        error= false;
 
1376
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1377
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1378
                            identifier.getTableName());
 
1379
        create_info->table_existed= 1;          // Mark that table existed
 
1380
      }
 
1381
      else 
 
1382
      {
 
1383
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1384
      }
 
1385
 
 
1386
      goto unlock_and_end;
 
1387
    }
 
1388
    /*
 
1389
      We don't assert here, but check the result, because the table could be
 
1390
      in the table definition cache and in the same time the .frm could be
 
1391
      missing from the disk, in case of manual intervention which deletes
 
1392
      the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
 
1393
      Then she could create the table. This case is pretty obscure and
 
1394
      therefore we don't introduce a new error message only for it.
 
1395
    */
 
1396
    if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
 
1397
    {
 
1398
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1399
      goto unlock_and_end;
 
1400
    }
 
1401
  }
 
1402
 
 
1403
  /*
 
1404
    Check that table with given name does not already
 
1405
    exist in any storage engine. In such a case it should
 
1406
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1407
    unless user specified CREATE TABLE IF EXISTS
 
1408
    The LOCK_open mutex has been locked to make sure no
 
1409
    one else is attempting to discover the table. Since
 
1410
    it's not on disk as a frm cursor, no one could be using it!
 
1411
  */
 
1412
  if (not lex_identified_temp_table)
 
1413
  {
 
1414
    bool exists= plugin::StorageEngine::doesTableExist(*session, identifier, false);
 
1415
 
 
1416
    if (exists)
 
1417
    {
 
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;
 
1430
    }
 
1431
  }
 
1432
 
 
1433
  session->set_proc_info("creating table");
 
1434
  create_info->table_existed= 0;                // Mark that table is created
 
1435
 
 
1436
  create_info->table_options= db_options;
 
1437
 
 
1438
  if (rea_create_table(session, identifier,
 
1439
                       table_proto,
 
1440
                       create_info, alter_info->create_list,
 
1441
                       key_count, key_info_buffer))
 
1442
  {
 
1443
    goto unlock_and_end;
 
1444
  }
 
1445
 
 
1446
  if (lex_identified_temp_table)
 
1447
  {
 
1448
    /* Open table and put in temporary table list */
 
1449
    if (not (session->open_temporary_table(identifier)))
 
1450
    {
 
1451
      (void) session->rm_temporary_table(identifier);
 
1452
      goto unlock_and_end;
 
1453
    }
 
1454
  }
 
1455
 
 
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
  }
 
1461
  error= false;
 
1462
unlock_and_end:
 
1463
  pthread_mutex_unlock(&LOCK_open);
 
1464
 
 
1465
err:
 
1466
  session->set_proc_info("After create");
 
1467
 
 
1468
  return(error);
1532
1469
}
1533
1470
 
1534
1471
 
1535
1472
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
 
1473
  Database locking aware wrapper for mysql_create_table_no_lock(),
1537
1474
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
 
1475
 
 
1476
bool mysql_create_table(Session *session,
 
1477
                        TableIdentifier &identifier,
1540
1478
                        HA_CREATE_INFO *create_info,
1541
1479
                        message::Table &table_proto,
1542
1480
                        AlterInfo *alter_info,
1544
1482
                        uint32_t select_field_count,
1545
1483
                        bool is_if_not_exists)
1546
1484
{
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);
 
1485
  Table *name_lock= NULL;
 
1486
  bool result;
 
1487
  bool lex_identified_temp_table=
 
1488
    (table_proto.type() == message::Table::TEMPORARY);
 
1489
 
 
1490
  if (not lex_identified_temp_table)
 
1491
  {
 
1492
    if (session->lock_table_name_if_not_cached(identifier.getDBName(),
 
1493
                                               identifier.getTableName(),
 
1494
                                               &name_lock))
 
1495
    {
 
1496
      result= true;
 
1497
      goto unlock;
 
1498
    }
 
1499
    if (name_lock == NULL)
 
1500
    {
 
1501
      if (is_if_not_exists)
 
1502
      {
 
1503
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1504
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1505
                            identifier.getTableName());
 
1506
        create_info->table_existed= 1;
 
1507
        result= false;
 
1508
      }
 
1509
      else
 
1510
      {
 
1511
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1512
        result= true;
 
1513
      }
 
1514
      goto unlock;
 
1515
    }
 
1516
  }
 
1517
 
 
1518
  result= mysql_create_table_no_lock(session,
 
1519
                                     identifier,
 
1520
                                     create_info,
 
1521
                                     table_proto,
 
1522
                                     alter_info,
 
1523
                                     internal_tmp_table,
 
1524
                                     select_field_count,
 
1525
                                     is_if_not_exists);
 
1526
 
 
1527
unlock:
 
1528
  if (name_lock)
 
1529
  {
 
1530
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
 
1531
    session->unlink_open_table(name_lock);
 
1532
    pthread_mutex_unlock(&LOCK_open);
 
1533
  }
 
1534
 
 
1535
  return(result);
1567
1536
}
1568
1537
 
1569
1538
 
1572
1541
**/
1573
1542
 
1574
1543
static bool
1575
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1544
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1576
1545
{
1577
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1546
  for (KEY *key=start ; key != end ; key++)
1578
1547
    if (!my_strcasecmp(system_charset_info,name,key->name))
1579
1548
      return 1;
1580
1549
  return 0;
1582
1551
 
1583
1552
 
1584
1553
static char *
1585
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1554
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1586
1555
{
1587
1556
  char buff[MAX_FIELD_NAME],*buff_end;
1588
1557
 
1616
1585
  Rename a table.
1617
1586
 
1618
1587
  SYNOPSIS
1619
 
    rename_table()
1620
 
      session
 
1588
    mysql_rename_table()
1621
1589
      base                      The plugin::StorageEngine handle.
1622
1590
      old_db                    The old database name.
1623
1591
      old_name                  The old table name.
1624
1592
      new_db                    The new database name.
1625
1593
      new_name                  The new table name.
 
1594
      flags                     flags for build_table_filename().
 
1595
                                FN_FROM_IS_TMP old_name is temporary.
 
1596
                                FN_TO_IS_TMP   new_name is temporary.
1626
1597
 
1627
1598
  RETURN
1628
1599
    false   OK
1630
1601
*/
1631
1602
 
1632
1603
bool
1633
 
rename_table(Session &session,
1634
 
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1604
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
 
1605
                   const char *old_name, const char *new_db,
 
1606
                   const char *new_name, uint32_t flags)
1637
1607
{
 
1608
  Session *session= current_session;
 
1609
  char from[FN_REFLEN], to[FN_REFLEN];
 
1610
  char *from_base= from, *to_base= to;
1638
1611
  int error= 0;
1639
1612
 
1640
1613
  assert(base);
1641
1614
 
1642
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
1615
  build_table_filename(from, sizeof(from), old_db, old_name,
 
1616
                       flags & FN_FROM_IS_TMP);
 
1617
  build_table_filename(to, sizeof(to), new_db, new_name,
 
1618
                       flags & FN_TO_IS_TMP);
 
1619
 
 
1620
  if (!(error= base->renameTable(session, from_base, to_base)))
1643
1621
  {
1644
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1645
 
    return true;
 
1622
    if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1623
       && rename_table_proto_file(from_base, to_base))
 
1624
    {
 
1625
      error= errno;
 
1626
      base->renameTable(session, to_base, from_base);
 
1627
    }
1646
1628
  }
1647
1629
 
1648
 
  error= base->renameTable(session, from, to);
1649
 
 
1650
1630
  if (error == HA_ERR_WRONG_COMMAND)
1651
 
  {
1652
1631
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1653
 
  }
1654
1632
  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; 
 
1633
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
1634
  return(error != 0);
1669
1635
}
1670
1636
 
1671
1637
 
1684
1650
   the table is closed.
1685
1651
 
1686
1652
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
1653
    Lock on LOCK_open
1688
1654
    Win32 clients must also have a WRITE LOCK on the table !
1689
1655
*/
1690
1656
 
1692
1658
                              enum ha_extra_function function)
1693
1659
{
1694
1660
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1661
  safe_mutex_assert_owner(&LOCK_open);
1696
1662
 
1697
1663
  table->cursor->extra(function);
1698
1664
  /* Mark all tables that are in use as 'old' */
1699
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1665
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1700
1666
 
1701
1667
  /* 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);
 
1668
  remove_table_from_cache(session, table->s->db.str,
 
1669
                          table->s->table_name.str,
 
1670
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1671
}
1705
1672
 
1706
1673
/*
1716
1683
    reopen the table.
1717
1684
 
1718
1685
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
1686
    Lock on LOCK_open
1720
1687
    Win32 clients must also have a WRITE LOCK on the table !
1721
1688
*/
1722
1689
 
1727
1694
  /* Close lock if this is not got with LOCK TABLES */
1728
1695
  if (lock)
1729
1696
  {
1730
 
    unlockTables(lock);
 
1697
    mysql_unlock_tables(this, lock);
1731
1698
    lock= NULL;                 // Start locked threads
1732
1699
  }
1733
1700
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
1701
  unlink_open_table(table);
1735
1702
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1737
 
  locking::broadcast_refresh();
 
1703
  /* When lock on LOCK_open is freed other threads can continue */
 
1704
  broadcast_refresh();
1738
1705
}
1739
1706
 
1740
1707
/*
1743
1710
    true  Message should be sent by caller
1744
1711
          (admin operation or network communication failed)
1745
1712
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
1713
static bool mysql_admin_table(Session* session, TableList* tables,
1747
1714
                              HA_CHECK_OPT* check_opt,
1748
1715
                              const char *operator_name,
1749
1716
                              thr_lock_type lock_type,
1772
1739
  item->maybe_null = 1;
1773
1740
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
1741
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
1742
  if (session->client->sendFields(&field_list))
1776
1743
    return true;
1777
1744
 
1778
1745
  for (table= tables; table; table= table->next_local)
1779
1746
  {
1780
1747
    char table_name[NAME_LEN*2+2];
 
1748
    char* db = table->db;
1781
1749
    bool fatal_error=0;
1782
1750
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
1751
    sprintf(table_name,"%s.%s",db,table->table_name);
1784
1752
    table->lock_type= lock_type;
1785
1753
    /* open only one table from local list of command */
1786
1754
    {
1793
1761
      /*
1794
1762
        Time zone tables and SP tables can be add to lex->query_tables list,
1795
1763
        so it have to be prepared.
1796
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
1764
        TODO: Investigate if we can put extra tables into argument instead of
 
1765
        using lex->query_tables
1797
1766
      */
1798
1767
      lex->query_tables= table;
1799
1768
      lex->query_tables_last= &table->next_global;
1827
1796
    {
1828
1797
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1798
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1799
      session->client->store(table_name);
 
1800
      session->client->store(operator_name);
 
1801
      session->client->store(STRING_WITH_LEN("error"));
1833
1802
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
1803
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
1804
      session->client->store(buff, length);
 
1805
      transaction_services.ha_autocommit_or_rollback(session, false);
1837
1806
      session->endTransaction(COMMIT);
1838
1807
      session->close_thread_tables();
1839
1808
      lex->reset_query_tables_list(false);
1840
1809
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
1810
      if (session->client->flush())
1842
1811
        goto err;
1843
1812
      continue;
1844
1813
    }
1845
1814
 
1846
1815
    /* Close all instances of the table to allow repair to rename files */
1847
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
1816
    if (lock_type == TL_WRITE && table->table->s->version)
1848
1817
    {
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);
 
1818
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
1819
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
1820
                                              "Waiting to get writelock");
 
1821
      mysql_lock_abort(session,table->table);
 
1822
      remove_table_from_cache(session, table->table->s->db.str,
 
1823
                              table->table->s->table_name.str,
 
1824
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
1825
                              RTFC_CHECK_KILLED_FLAG);
1855
1826
      session->exit_cond(old_message);
1856
 
      if (session->getKilled())
 
1827
      if (session->killed)
1857
1828
        goto err;
1858
1829
      open_for_modify= 0;
1859
1830
    }
1869
1840
      DRIZZLE_ERROR *err;
1870
1841
      while ((err= it++))
1871
1842
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
1843
        session->client->store(table_name);
 
1844
        session->client->store(operator_name);
 
1845
        session->client->store(warning_level_names[err->level].str,
1875
1846
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
1847
        session->client->store(err->msg);
 
1848
        if (session->client->flush())
1878
1849
          goto err;
1879
1850
      }
1880
1851
      drizzle_reset_errors(session, true);
1881
1852
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
1853
    session->client->store(table_name);
 
1854
    session->client->store(operator_name);
1884
1855
 
1885
1856
    switch (result_code) {
1886
1857
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
1859
        char buf[ERRMSGSIZE+20];
1889
1860
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
1861
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
1862
        session->client->store(STRING_WITH_LEN("note"));
 
1863
        session->client->store(buf, length);
1893
1864
      }
1894
1865
      break;
1895
1866
 
1896
1867
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
1868
      session->client->store(STRING_WITH_LEN("status"));
 
1869
      session->client->store(STRING_WITH_LEN("OK"));
1899
1870
      break;
1900
1871
 
1901
1872
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
1873
      session->client->store(STRING_WITH_LEN("status"));
 
1874
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
1875
      break;
1905
1876
 
1906
1877
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
1878
      session->client->store(STRING_WITH_LEN("status"));
 
1879
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
1880
      open_for_modify= false;
1910
1881
      break;
1911
1882
 
1912
1883
    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"));
 
1884
      session->client->store(STRING_WITH_LEN("status"));
 
1885
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
1886
      break;
1916
1887
 
1917
1888
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
1889
      session->client->store(STRING_WITH_LEN("error"));
 
1890
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
1891
      fatal_error=1;
1921
1892
      break;
1922
1893
 
1923
1894
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
1895
      session->client->store(STRING_WITH_LEN("error"));
 
1896
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1926
1897
      break;
1927
1898
 
1928
1899
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1931
1902
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
1903
                             _("Unknown - internal error %d during operation"),
1933
1904
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
1905
        session->client->store(STRING_WITH_LEN("error"));
 
1906
        session->client->store(buf, length);
1936
1907
        fatal_error=1;
1937
1908
        break;
1938
1909
      }
1940
1911
    if (table->table)
1941
1912
    {
1942
1913
      if (fatal_error)
1943
 
      {
1944
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1945
 
      }
 
1914
        table->table->s->version=0;               // Force close of table
1946
1915
      else if (open_for_modify)
1947
1916
      {
1948
 
        if (table->table->getShare()->getType())
1949
 
        {
 
1917
        if (table->table->s->tmp_table)
1950
1918
          table->table->cursor->info(HA_STATUS_CONST);
1951
 
        }
1952
1919
        else
1953
1920
        {
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);
 
1921
          pthread_mutex_lock(&LOCK_open);
 
1922
          remove_table_from_cache(session, table->table->s->db.str,
 
1923
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
1924
          pthread_mutex_unlock(&LOCK_open);
1957
1925
        }
1958
1926
      }
1959
1927
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
1928
    transaction_services.ha_autocommit_or_rollback(session, false);
1961
1929
    session->endTransaction(COMMIT);
1962
1930
    session->close_thread_tables();
1963
1931
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
1932
    if (session->client->flush())
1965
1933
      goto err;
1966
1934
  }
1967
1935
 
1969
1937
  return(false);
1970
1938
 
1971
1939
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
1940
  transaction_services.ha_autocommit_or_rollback(session, true);
1973
1941
  session->endTransaction(ROLLBACK);
1974
1942
  session->close_thread_tables();                       // Shouldn't be needed
1975
1943
  if (table)
1977
1945
  return(true);
1978
1946
}
1979
1947
 
 
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
 
1980
2003
  /*
1981
2004
    Create a new table by copying from source table
1982
2005
 
1983
2006
    Altough exclusive name-lock on target table protects us from concurrent
1984
2007
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2008
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
2009
    LOCK_open in order to provide minimal atomicity against operations which
1987
2010
    disregard name-locks, like I_S implementation, for example. This is a
1988
2011
    temporary and should not be copied. Instead we should fix our code to
1989
2012
    always honor name-locks.
1990
2013
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
2014
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2015
    during the call to plugin::StorageEngine::createTable().
1993
2016
    See bug #28614 for more info.
1994
2017
  */
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)
 
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)
2000
2022
{
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);
 
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
 
2012
2056
    return false;
2013
2057
  }
2014
2058
 
2015
 
  new_table_message.CopyFrom(*source_table_message);
2016
 
 
2017
 
  if (destination_identifier.isTmp())
2018
 
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
2020
 
  }
2021
 
  else
2022
 
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
2024
 
  }
2025
 
 
2026
 
  if (is_engine_set)
2027
 
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2029
 
  }
2030
 
 
2031
 
  { // We now do a selective copy of elements on to the new table.
2032
 
    new_table_message.set_name(create_table_proto.name());
2033
 
    new_table_message.set_schema(create_table_proto.schema());
2034
 
    new_table_message.set_catalog(create_table_proto.catalog());
2035
 
  }
2036
 
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2039
 
  {
2040
 
    if (new_table_message.fk_constraint(j).has_name())
2041
 
    {
2042
 
      std::string name(new_table_message.name());
2043
 
      char number[20];
2044
 
 
2045
 
      name.append("_ibfk_");
2046
 
      snprintf(number, sizeof(number), "%d", j+1);
2047
 
      name.append(number);
2048
 
 
2049
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
 
      pfkey->set_name(name);
2051
 
    }
2052
 
  }
2053
 
 
2054
2059
  /*
2055
2060
    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).
 
2061
    creation, instead create the table directly (for both normal
 
2062
    and temporary tables).
2057
2063
  */
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;
 
2064
  int err= plugin::StorageEngine::createTable(session,
 
2065
                                              destination_identifier,
 
2066
                                              true, new_proto);
 
2067
 
 
2068
  return err ? false : true;
2069
2069
}
2070
2070
 
2071
2071
/*
2072
2072
  Create a table identical to the specified table
2073
2073
 
2074
2074
  SYNOPSIS
2075
 
    create_like_table()
 
2075
    mysql_create_like_table()
2076
2076
    session             Thread object
2077
2077
    table       Table list element for target table
2078
2078
    src_table   Table list element for source table
2083
2083
    true  error
2084
2084
*/
2085
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)
 
2086
bool mysql_create_like_table(Session* session,
 
2087
                             TableIdentifier &destination_identifier,
 
2088
                             TableList* table, TableList* src_table,
 
2089
                             message::Table& create_table_proto,
 
2090
                             bool is_if_not_exists,
 
2091
                             bool is_engine_set)
2092
2092
{
 
2093
  Table *name_lock= 0;
 
2094
  char *db= table->db;
 
2095
  char *table_name= table->table_name;
2093
2096
  bool res= true;
2094
 
  bool table_exists= false;
 
2097
  uint32_t not_used;
 
2098
  bool lex_identified_temp_table=
 
2099
    (create_table_proto.type() == message::Table::TEMPORARY);
 
2100
  bool was_created;
 
2101
 
 
2102
  /*
 
2103
    By opening source table we guarantee that it exists and no concurrent
 
2104
    DDL operation will mess with it. Later we also take an exclusive
 
2105
    name-lock on target table name, which makes copying of .frm cursor,
 
2106
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2107
    against concurrent DML and DDL operations on target table.
 
2108
    Thus by holding both these "locks" we ensure that our statement is
 
2109
    properly isolated from all concurrent operations which matter.
 
2110
  */
 
2111
  if (session->open_tables_from_list(&src_table, &not_used))
 
2112
    return true;
 
2113
 
 
2114
  TableIdentifier src_identifier(src_table->table->s->db.str,
 
2115
                                 src_table->table->s->table_name.str, src_table->table->s->tmp_table);
 
2116
 
 
2117
 
2095
2118
 
2096
2119
  /*
2097
2120
    Check that destination tables does not exist. Note that its name
2098
2121
    was already checked when it was added to the table list.
2099
 
 
2100
 
    For temporary tables we don't aim to grab locks.
2101
2122
  */
2102
 
  if (destination_identifier.isTmp())
 
2123
  bool table_exists= false;
 
2124
  if (lex_identified_temp_table)
2103
2125
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
 
2126
    if (session->find_temporary_table(db, table_name))
2105
2127
    {
2106
2128
      table_exists= true;
2107
2129
    }
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
  }
2130
 
  else // Standard table which will require locks.
 
2131
  else
2131
2132
  {
2132
 
    Table *name_lock= 0;
2133
 
 
2134
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
 
2133
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2135
2134
    {
2136
2135
      if (name_lock)
2137
2136
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2137
        pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2139
2138
        session->unlink_open_table(name_lock);
 
2139
        pthread_mutex_unlock(&LOCK_open);
2140
2140
      }
2141
2141
 
2142
2142
      return res;
2150
2150
    {
2151
2151
      table_exists= true;
2152
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
2153
  }
2180
2154
 
2181
2155
  if (table_exists)
2184
2158
    {
2185
2159
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
2160
      snprintf(warn_buff, sizeof(warn_buff),
2187
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2161
               ER(ER_TABLE_EXISTS_ERROR), table_name);
2188
2162
      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;
 
2163
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2164
      res= false;
 
2165
    }
 
2166
    else
 
2167
    {
 
2168
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2169
    }
 
2170
  }
 
2171
  else // Otherwise we create the table
 
2172
  {
 
2173
    pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2174
    was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2175
                                      src_identifier, lex_identified_temp_table, is_engine_set);
 
2176
    pthread_mutex_unlock(&LOCK_open);
 
2177
 
 
2178
    // So we blew the creation of the table, and we scramble to clean up
 
2179
    // anything that might have been created (read... it is a hack)
 
2180
    if (not was_created)
 
2181
    {
 
2182
      if (lex_identified_temp_table)
 
2183
      {
 
2184
        (void) session->rm_temporary_table(destination_identifier);
 
2185
      }
 
2186
      else
 
2187
      {
 
2188
        quick_rm_table(*session, destination_identifier);
 
2189
      }
 
2190
    } 
 
2191
    else if (lex_identified_temp_table && not session->open_temporary_table(destination_identifier))
 
2192
    {
 
2193
      // We created, but we can't open... also, a hack.
 
2194
      (void) session->rm_temporary_table(destination_identifier);
 
2195
    }
 
2196
    else
 
2197
    {
 
2198
      if (not lex_identified_temp_table)
 
2199
      {
 
2200
        bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
 
2201
        (void)rc;
 
2202
      }
 
2203
 
 
2204
      res= false;
 
2205
    }
 
2206
  }
 
2207
 
 
2208
  if (name_lock)
 
2209
  {
 
2210
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2211
    session->unlink_open_table(name_lock);
 
2212
    pthread_mutex_unlock(&LOCK_open);
 
2213
  }
 
2214
 
 
2215
  return(res);
2199
2216
}
2200
2217
 
2201
2218
 
2202
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2219
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
2220
{
2204
2221
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
2222
 
2206
 
  return(admin_table(session, tables, check_opt,
 
2223
  return(mysql_admin_table(session, tables, check_opt,
2207
2224
                                "analyze", lock_type, true,
2208
2225
                                &Cursor::ha_analyze));
2209
2226
}
2210
2227
 
2211
2228
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2229
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
2230
{
2214
2231
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
2232
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2233
  return(mysql_admin_table(session, tables, check_opt,
2217
2234
                                "check", lock_type,
2218
2235
                                false,
2219
2236
                                &Cursor::ha_check));
2220
2237
}
2221
2238
 
 
2239
 
 
2240
bool mysql_checksum_table(Session *session, TableList *tables,
 
2241
                          HA_CHECK_OPT *)
 
2242
{
 
2243
  TableList *table;
 
2244
  List<Item> field_list;
 
2245
  Item *item;
 
2246
 
 
2247
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
2248
  item->maybe_null= 1;
 
2249
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
2250
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
2251
  item->maybe_null= 1;
 
2252
  if (session->client->sendFields(&field_list))
 
2253
    return true;
 
2254
 
 
2255
  /* Open one table after the other to keep lock time as short as possible. */
 
2256
  for (table= tables; table; table= table->next_local)
 
2257
  {
 
2258
    char table_name[NAME_LEN*2+2];
 
2259
    Table *t;
 
2260
 
 
2261
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2262
 
 
2263
    t= table->table= session->openTableLock(table, TL_READ);
 
2264
    session->clear_error();                     // these errors shouldn't get client
 
2265
 
 
2266
    session->client->store(table_name);
 
2267
 
 
2268
    if (!t)
 
2269
    {
 
2270
      /* Table didn't exist */
 
2271
      session->client->store();
 
2272
      session->clear_error();
 
2273
    }
 
2274
    else
 
2275
    {
 
2276
      /**
 
2277
        @note if the engine keeps a checksum then we return the checksum, otherwise we calculate
 
2278
      */
 
2279
      if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
 
2280
      {
 
2281
        session->client->store((uint64_t)t->cursor->checksum());
 
2282
      }
 
2283
      else
 
2284
      {
 
2285
        /* calculating table's checksum */
 
2286
        internal::ha_checksum crc= 0;
 
2287
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2288
 
 
2289
        t->use_all_columns();
 
2290
 
 
2291
        if (t->cursor->ha_rnd_init(1))
 
2292
          session->client->store();
 
2293
        else
 
2294
        {
 
2295
          for (;;)
 
2296
          {
 
2297
            internal::ha_checksum row_crc= 0;
 
2298
            int error= t->cursor->rnd_next(t->record[0]);
 
2299
            if (unlikely(error))
 
2300
            {
 
2301
              if (error == HA_ERR_RECORD_DELETED)
 
2302
                continue;
 
2303
              break;
 
2304
            }
 
2305
            if (t->s->null_bytes)
 
2306
            {
 
2307
              /* fix undefined null bits */
 
2308
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
2309
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
2310
                t->record[0][0] |= 1;
 
2311
 
 
2312
              row_crc= internal::my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
2313
            }
 
2314
 
 
2315
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
2316
            {
 
2317
              Field *f= t->field[i];
 
2318
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
2319
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
2320
              {
 
2321
                String tmp;
 
2322
                f->val_str(&tmp);
 
2323
                row_crc= internal::my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
2324
              }
 
2325
              else
 
2326
                row_crc= internal::my_checksum(row_crc, f->ptr,
 
2327
                                     f->pack_length());
 
2328
            }
 
2329
 
 
2330
            crc+= row_crc;
 
2331
          }
 
2332
          session->client->store((uint64_t)crc);
 
2333
          t->cursor->ha_rnd_end();
 
2334
        }
 
2335
      }
 
2336
      session->clear_error();
 
2337
      session->close_thread_tables();
 
2338
      table->table=0;                           // For query cache
 
2339
    }
 
2340
    if (session->client->flush())
 
2341
      goto err;
 
2342
  }
 
2343
 
 
2344
  session->my_eof();
 
2345
  return(false);
 
2346
 
 
2347
 err:
 
2348
  session->close_thread_tables();                       // Shouldn't be needed
 
2349
  if (table)
 
2350
    table->table=0;
 
2351
  return(true);
 
2352
}
 
2353
 
2222
2354
} /* namespace drizzled */