~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: lbieber
  • Date: 2010-10-07 21:44:19 UTC
  • mfrom: (1812.4.2 staging)
  • mto: This revision was merged to the branch mainline in revision 1822.
  • Revision ID: lbieber@orisndriz08-20101007214419-0w3k9dlvlnt57tah
Merge Brian - fixu bug #655558: SELECT 102/(1-1) should error on divide by zero          

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
18
 
#include <config.h>
 
18
#include "config.h"
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
 
#include <drizzled/strfunc.h>
 
29
#include "drizzled/strfunc.h"
 
30
#include <drizzled/db.h>
30
31
#include <drizzled/lock.h>
31
32
#include <drizzled/unireg.h>
32
33
#include <drizzled/item/int.h>
33
34
#include <drizzled/item/empty_string.h>
34
35
#include <drizzled/transaction_services.h>
35
 
#include <drizzled/transaction_services.h>
 
36
#include "drizzled/transaction_services.h"
36
37
#include <drizzled/table_proto.h>
37
38
#include <drizzled/plugin/client.h>
38
39
#include <drizzled/identifier.h>
39
 
#include <drizzled/internal/m_string.h>
40
 
#include <drizzled/global_charset_info.h>
41
 
#include <drizzled/charset.h>
42
 
 
43
 
#include <drizzled/definition/cache.h>
44
 
 
45
 
#include <drizzled/statement/alter_table.h>
46
 
#include <drizzled/sql_table.h>
47
 
#include <drizzled/pthread_globals.h>
48
 
#include <drizzled/typelib.h>
49
 
#include <drizzled/plugin/storage_engine.h>
 
40
#include "drizzled/internal/m_string.h"
 
41
#include "drizzled/global_charset_info.h"
 
42
#include "drizzled/charset.h"
 
43
 
 
44
 
 
45
#include "drizzled/statement/alter_table.h"
 
46
#include "drizzled/sql_table.h"
 
47
#include "drizzled/pthread_globals.h"
50
48
 
51
49
#include <algorithm>
52
50
#include <sstream>
58
56
namespace drizzled
59
57
{
60
58
 
 
59
extern pid_t current_pid;
 
60
 
61
61
bool is_primary_key(KeyInfo *key_info)
62
62
{
63
63
  static const char * primary_key_name="PRIMARY";
85
85
    let's fetch the database default character set and
86
86
    apply it to the table.
87
87
  */
88
 
  identifier::Schema identifier(db);
 
88
  SchemaIdentifier identifier(db);
89
89
  if (create_info->default_table_charset == NULL)
90
90
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
91
91
}
105
105
    cursor
106
106
*/
107
107
 
108
 
void write_bin_log(Session *session, const std::string &query)
 
108
void write_bin_log(Session *session,
 
109
                   char const *query)
109
110
{
110
111
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(*session, query);
 
112
  transaction_services.rawStatement(session, query);
112
113
}
113
114
 
114
115
/*
115
116
  Execute the drop of a normal or temporary table
116
117
 
117
118
  SYNOPSIS
118
 
    rm_table_part2()
 
119
    mysql_rm_table_part2()
119
120
    session                     Thread Cursor
120
121
    tables              Tables to drop
121
122
    if_exists           If set, don't give an error if table doesn't exists.
138
139
   -1   Thread was killed
139
140
*/
140
141
 
141
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
 
                   bool drop_temporary)
 
142
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
143
                         bool drop_temporary)
143
144
{
144
145
  TableList *table;
145
 
  util::string::vector wrong_tables;
 
146
  String wrong_tables;
146
147
  int error= 0;
147
148
  bool foreign_key_error= false;
148
149
 
149
 
  do
150
 
  {
151
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
152
 
 
153
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
154
 
    {
155
 
      return 1;
156
 
    }
157
 
 
158
 
    /* Don't give warnings for not found errors, as we already generate notes */
159
 
    session->no_warnings_for_error= 1;
160
 
 
161
 
    for (table= tables; table; table= table->next_local)
162
 
    {
163
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
164
 
 
165
 
      error= session->drop_temporary_table(tmp_identifier);
166
 
 
167
 
      switch (error) {
168
 
      case  0:
169
 
        // removed temporary table
170
 
        continue;
171
 
      case -1:
 
150
  LOCK_open.lock(); /* Part 2 of rm a table */
 
151
 
 
152
  /*
 
153
    If we have the table in the definition cache, we don't have to check the
 
154
    .frm cursor to find if the table is a normal table (not view) and what
 
155
    engine to use.
 
156
  */
 
157
 
 
158
  for (table= tables; table; table= table->next_local)
 
159
  {
 
160
    TableIdentifier identifier(table->db, table->table_name);
 
161
    TableShare *share;
 
162
    table->setDbType(NULL);
 
163
 
 
164
    if ((share= TableShare::getShare(identifier)))
 
165
    {
 
166
      table->setDbType(share->db_type());
 
167
    }
 
168
  }
 
169
 
 
170
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
171
  {
 
172
    LOCK_open.unlock();
 
173
    return 1;
 
174
  }
 
175
 
 
176
  /* Don't give warnings for not found errors, as we already generate notes */
 
177
  session->no_warnings_for_error= 1;
 
178
 
 
179
  for (table= tables; table; table= table->next_local)
 
180
  {
 
181
    char *db=table->db;
 
182
 
 
183
    error= session->drop_temporary_table(table);
 
184
 
 
185
    switch (error) {
 
186
    case  0:
 
187
      // removed temporary table
 
188
      continue;
 
189
    case -1:
 
190
      error= 1;
 
191
      goto err_with_placeholders;
 
192
    default:
 
193
      // temporary table not found
 
194
      error= 0;
 
195
    }
 
196
 
 
197
    if (drop_temporary == false)
 
198
    {
 
199
      Table *locked_table;
 
200
      TableIdentifier identifier(db, table->table_name);
 
201
      abort_locked_tables(session, identifier);
 
202
      remove_table_from_cache(session, identifier,
 
203
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
204
                              RTFC_CHECK_KILLED_FLAG);
 
205
      /*
 
206
        If the table was used in lock tables, remember it so that
 
207
        unlock_table_names can free it
 
208
      */
 
209
      if ((locked_table= drop_locked_tables(session, identifier)))
 
210
        table->table= locked_table;
 
211
 
 
212
      if (session->killed)
 
213
      {
 
214
        error= -1;
 
215
        goto err_with_placeholders;
 
216
      }
 
217
    }
 
218
    TableIdentifier identifier(db, table->table_name, table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
 
219
 
 
220
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
221
    {
 
222
      // Table was not found on disk and table can't be created from engine
 
223
      if (if_exists)
 
224
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
225
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
226
                            table->table_name);
 
227
      else
172
228
        error= 1;
173
 
        break;
174
 
      default:
175
 
        // temporary table not found
 
229
    }
 
230
    else
 
231
    {
 
232
      error= plugin::StorageEngine::dropTable(*session, identifier);
 
233
 
 
234
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
235
      {
176
236
        error= 0;
177
 
      }
178
 
 
179
 
      if (drop_temporary == false)
180
 
      {
181
 
        Table *locked_table;
182
 
        abort_locked_tables(session, tmp_identifier);
183
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
184
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
185
 
                                              RTFC_CHECK_KILLED_FLAG);
186
 
        /*
187
 
          If the table was used in lock tables, remember it so that
188
 
          unlock_table_names can free it
189
 
        */
190
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
191
 
          table->table= locked_table;
192
 
 
193
 
        if (session->getKilled())
194
 
        {
195
 
          error= -1;
196
 
          break;
197
 
        }
198
 
      }
199
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
200
 
 
201
 
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
202
 
 
203
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
 
      {
205
 
        // Table was not found on disk and table can't be created from engine
206
 
        if (if_exists)
207
 
        {
208
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
 
                              table->getTableName());
211
 
        }
212
 
        else
213
 
        {
214
 
          error= 1;
215
 
        }
216
 
      }
217
 
      else
218
 
      {
219
 
        drizzled::error_t local_error;
220
 
 
221
 
        /* Generate transaction event ONLY when we successfully drop */ 
222
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
223
 
        {
224
 
          if (message) // If we have no definition, we don't know if the table should have been replicated
225
 
          {
226
 
            TransactionServices &transaction_services= TransactionServices::singleton();
227
 
            transaction_services.dropTable(*session, identifier, *message, if_exists);
228
 
          }
229
 
        }
230
 
        else
231
 
        {
232
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
233
 
          {
234
 
            error= 0;
235
 
            session->clear_error();
236
 
          }
237
 
 
238
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
239
 
          {
240
 
            /* the table is referenced by a foreign key constraint */
241
 
            foreign_key_error= true;
242
 
          }
243
 
          error= local_error;
244
 
        }
245
 
      }
246
 
 
247
 
      if (error)
248
 
      {
249
 
        wrong_tables.push_back(table->getTableName());
250
 
      }
251
 
    }
252
 
 
253
 
    tables->unlock_table_names();
254
 
 
255
 
  } while (0);
256
 
 
257
 
  if (wrong_tables.size())
 
237
        session->clear_error();
 
238
      }
 
239
 
 
240
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
241
      {
 
242
        /* the table is referenced by a foreign key constraint */
 
243
        foreign_key_error= true;
 
244
      }
 
245
    }
 
246
 
 
247
    if (error == 0 || (if_exists && foreign_key_error == false))
 
248
    {
 
249
      TransactionServices &transaction_services= TransactionServices::singleton();
 
250
      transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
 
251
    }
 
252
 
 
253
    if (error)
 
254
    {
 
255
      if (wrong_tables.length())
 
256
        wrong_tables.append(',');
 
257
      wrong_tables.append(String(table->table_name,system_charset_info));
 
258
    }
 
259
  }
 
260
  /*
 
261
    It's safe to unlock LOCK_open: we have an exclusive lock
 
262
    on the table name.
 
263
  */
 
264
  LOCK_open.unlock();
 
265
  error= 0;
 
266
 
 
267
  if (wrong_tables.length())
258
268
  {
259
269
    if (not foreign_key_error)
260
270
    {
261
 
      std::string table_error;
262
 
 
263
 
      for (util::string::vector::iterator iter= wrong_tables.begin();
264
 
           iter != wrong_tables.end();
265
 
           iter++)
266
 
      {
267
 
        table_error+= *iter;
268
 
        table_error+= ',';
269
 
      }
270
 
      table_error.resize(table_error.size() -1);
271
 
 
272
271
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
 
                      table_error.c_str());
 
272
                      wrong_tables.c_ptr());
274
273
    }
275
274
    else
276
275
    {
279
278
    error= 1;
280
279
  }
281
280
 
 
281
  LOCK_open.lock(); /* final bit in rm table lock */
 
282
 
 
283
err_with_placeholders:
 
284
  unlock_table_names(tables, NULL);
 
285
  LOCK_open.unlock();
282
286
  session->no_warnings_for_error= 0;
283
287
 
284
288
  return error;
285
289
}
286
290
 
 
291
 
 
292
/*
 
293
  Quickly remove a table.
 
294
 
 
295
  SYNOPSIS
 
296
    quick_rm_table()
 
297
      base                      The plugin::StorageEngine handle.
 
298
      db                        The database name.
 
299
      table_name                The table name.
 
300
      is_tmp                    If the table is temp.
 
301
 
 
302
  RETURN
 
303
    0           OK
 
304
    != 0        Error
 
305
*/
 
306
bool quick_rm_table(Session& session,
 
307
                    TableIdentifier &identifier)
 
308
{
 
309
  return (plugin::StorageEngine::dropTable(session, identifier));
 
310
}
 
311
 
287
312
/*
288
313
  Sort keys in the following order:
289
314
  - PRIMARY KEY
483
508
    sql_field->length= 8; // Unireg field length
484
509
    (*blob_columns)++;
485
510
    break;
486
 
 
 
511
  case DRIZZLE_TYPE_VARCHAR:
 
512
    break;
487
513
  case DRIZZLE_TYPE_ENUM:
488
 
    {
489
 
      if (check_duplicates_in_interval("ENUM",
490
 
                                       sql_field->field_name,
491
 
                                       sql_field->interval,
492
 
                                       sql_field->charset,
493
 
                                       &dup_val_count))
494
 
      {
495
 
        return 1;
496
 
      }
497
 
    }
498
 
    break;
499
 
 
500
 
  case DRIZZLE_TYPE_MICROTIME:
 
514
    if (check_duplicates_in_interval("ENUM",
 
515
                                     sql_field->field_name,
 
516
                                     sql_field->interval,
 
517
                                     sql_field->charset,
 
518
                                     &dup_val_count))
 
519
      return 1;
 
520
    break;
 
521
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
522
  case DRIZZLE_TYPE_DATETIME:
 
523
  case DRIZZLE_TYPE_NULL:
 
524
    break;
 
525
  case DRIZZLE_TYPE_DECIMAL:
 
526
    break;
501
527
  case DRIZZLE_TYPE_TIMESTAMP:
502
528
    /* We should replace old TIMESTAMP fields with their newer analogs */
503
529
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
513
539
      }
514
540
    }
515
541
    else if (sql_field->unireg_check != Field::NONE)
516
 
    {
517
542
      (*timestamps_with_niladic)++;
518
 
    }
519
543
 
520
544
    (*timestamps)++;
521
 
 
522
 
    break;
523
 
 
524
 
  case DRIZZLE_TYPE_BOOLEAN:
525
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
526
 
  case DRIZZLE_TYPE_DATETIME:
527
 
  case DRIZZLE_TYPE_DECIMAL:
528
 
  case DRIZZLE_TYPE_DOUBLE:
529
 
  case DRIZZLE_TYPE_LONG:
530
 
  case DRIZZLE_TYPE_LONGLONG:
531
 
  case DRIZZLE_TYPE_NULL:
532
 
  case DRIZZLE_TYPE_TIME:
533
 
  case DRIZZLE_TYPE_UUID:
534
 
  case DRIZZLE_TYPE_VARCHAR:
 
545
    /* fall-through */
 
546
  default:
535
547
    break;
536
548
  }
537
549
 
538
550
  return 0;
539
551
}
540
552
 
541
 
static int prepare_create_table(Session *session,
542
 
                                HA_CREATE_INFO *create_info,
543
 
                                message::Table &create_proto,
544
 
                                AlterInfo *alter_info,
545
 
                                bool tmp_table,
546
 
                                uint32_t *db_options,
547
 
                                KeyInfo **key_info_buffer,
548
 
                                uint32_t *key_count,
549
 
                                int select_field_count)
 
553
static int mysql_prepare_create_table(Session *session,
 
554
                                      HA_CREATE_INFO *create_info,
 
555
                                      message::Table &create_proto,
 
556
                                      AlterInfo *alter_info,
 
557
                                      bool tmp_table,
 
558
                                      uint32_t *db_options,
 
559
                                      KeyInfo **key_info_buffer,
 
560
                                      uint32_t *key_count,
 
561
                                      int select_field_count)
550
562
{
551
563
  const char    *key_name;
552
564
  CreateField   *sql_field,*dup_field;
555
567
  KeyInfo               *key_info;
556
568
  KeyPartInfo *key_part_info;
557
569
  int           timestamps= 0, timestamps_with_niladic= 0;
558
 
  int           dup_no;
 
570
  int           field_no,dup_no;
559
571
  int           select_field_pos,auto_increment=0;
560
 
  List<CreateField>::iterator it(alter_info->create_list.begin());
561
 
  List<CreateField>::iterator it2(alter_info->create_list.begin());
 
572
  List_iterator<CreateField> it(alter_info->create_list);
 
573
  List_iterator<CreateField> it2(alter_info->create_list);
562
574
  uint32_t total_uneven_bit_length= 0;
563
575
 
564
576
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
567
579
  null_fields=blob_columns=0;
568
580
  max_key_length= engine->max_key_length();
569
581
 
570
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
582
  for (field_no=0; (sql_field=it++) ; field_no++)
571
583
  {
572
584
    const CHARSET_INFO *save_cs;
573
585
 
577
589
      executing a prepared statement for the second time.
578
590
    */
579
591
    sql_field->length= sql_field->char_length;
580
 
 
581
592
    if (!sql_field->charset)
582
593
      sql_field->charset= create_info->default_table_charset;
583
 
 
584
594
    /*
585
595
      table_charset is set in ALTER Table if we want change character set
586
596
      for all varchar/char columns.
652
662
        interval= sql_field->interval= typelib(session->mem_root,
653
663
                                               sql_field->interval_list);
654
664
 
655
 
        List<String>::iterator int_it(sql_field->interval_list.begin());
 
665
        List_iterator<String> int_it(sql_field->interval_list);
656
666
        String conv, *tmp;
657
667
        char comma_buf[4];
658
668
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
678
688
          interval->type_lengths[i]= lengthsp;
679
689
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
680
690
        }
681
 
        sql_field->interval_list.clear(); // Don't need interval_list anymore
 
691
        sql_field->interval_list.empty(); // Don't need interval_list anymore
682
692
      }
683
693
 
684
694
      /* DRIZZLE_TYPE_ENUM */
701
711
          else /* not NULL */
702
712
          {
703
713
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
704
 
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
 
714
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
705
715
            {
706
716
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
707
717
              return(true);
778
788
    if (not create_proto.engine().name().compare("MyISAM") &&
779
789
        ((sql_field->flags & BLOB_FLAG) ||
780
790
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
781
 
    {
782
791
      (*db_options)|= HA_OPTION_PACK_RECORD;
783
 
    }
784
 
 
785
 
    it2= alter_info->create_list.begin();
 
792
    it2.rewind();
786
793
  }
787
794
 
788
795
  /* record_offset will be increased with 'length-of-null-bits' later */
789
796
  record_offset= 0;
790
797
  null_fields+= total_uneven_bit_length;
791
798
 
792
 
  it= alter_info->create_list.begin();
 
799
  it.rewind();
793
800
  while ((sql_field=it++))
794
801
  {
795
802
    assert(sql_field->charset != 0);
829
836
 
830
837
  /* Create keys */
831
838
 
832
 
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
833
 
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
 
839
  List_iterator<Key> key_iterator(alter_info->key_list);
 
840
  List_iterator<Key> key_iterator2(alter_info->key_list);
834
841
  uint32_t key_parts=0, fk_key_count=0;
835
842
  bool primary_key=0,unique_key=0;
836
843
  Key *key, *key2;
880
887
    }
881
888
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
882
889
      return(true);
883
 
    key_iterator2= alter_info->key_list.begin();
 
890
    key_iterator2.rewind ();
884
891
    if (key->type != Key::FOREIGN_KEY)
885
892
    {
886
893
      while ((key2 = key_iterator2++) != key)
933
940
  if (!*key_info_buffer || ! key_part_info)
934
941
    return(true);                               // Out of memory
935
942
 
936
 
  key_iterator= alter_info->key_list.begin();
 
943
  key_iterator.rewind();
937
944
  key_number=0;
938
945
  for (; (key=key_iterator++) ; key_number++)
939
946
  {
992
999
 
993
1000
    message::Table::Field *protofield= NULL;
994
1001
 
995
 
    List<Key_part_spec>::iterator cols(key->columns.begin());
996
 
    List<Key_part_spec>::iterator cols2(key->columns.begin());
 
1002
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
997
1003
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
998
1004
    {
999
1005
      uint32_t length;
1000
1006
      Key_part_spec *dup_column;
1001
1007
      int proto_field_nr= 0;
1002
1008
 
1003
 
      it= alter_info->create_list.begin();
 
1009
      it.rewind();
1004
1010
      field=0;
1005
1011
      while ((sql_field=it++) && ++proto_field_nr &&
1006
1012
             my_strcasecmp(system_charset_info,
1007
1013
                           column->field_name.str,
1008
1014
                           sql_field->field_name))
1009
 
      {
1010
1015
        field++;
1011
 
      }
1012
 
 
1013
1016
      if (!sql_field)
1014
1017
      {
1015
1018
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1016
1019
        return(true);
1017
1020
      }
1018
 
 
1019
1021
      while ((dup_column= cols2++) != column)
1020
1022
      {
1021
1023
        if (!my_strcasecmp(system_charset_info,
1027
1029
          return(true);
1028
1030
        }
1029
1031
      }
1030
 
      cols2= key->columns.begin();
 
1032
      cols2.rewind();
1031
1033
 
1032
1034
      if (create_proto.field_size() > 0)
1033
1035
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1048
1050
            return true;
1049
1051
          }
1050
1052
        }
1051
 
 
1052
1053
        if (! (sql_field->flags & NOT_NULL_FLAG))
1053
1054
        {
1054
1055
          if (key->type == Key::PRIMARY)
1061
1062
            {
1062
1063
              message::Table::Field::FieldConstraints *constraints;
1063
1064
              constraints= protofield->mutable_constraints();
1064
 
              constraints->set_is_notnull(true);
 
1065
              constraints->set_is_nullable(false);
1065
1066
            }
1066
1067
 
1067
1068
          }
1075
1076
            }
1076
1077
          }
1077
1078
        }
1078
 
 
1079
1079
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1080
1080
        {
1081
1081
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1200
1200
        key_info->name=(char*) key_name;
1201
1201
      }
1202
1202
    }
1203
 
 
1204
1203
    if (!key_info->name || check_column_name(key_info->name))
1205
1204
    {
1206
1205
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1207
1206
      return(true);
1208
1207
    }
1209
 
 
1210
1208
    if (!(key_info->flags & HA_NULL_PART_KEY))
1211
 
    {
1212
1209
      unique_key=1;
1213
 
    }
1214
 
 
1215
1210
    key_info->key_length=(uint16_t) key_length;
1216
 
 
1217
1211
    if (key_length > max_key_length)
1218
1212
    {
1219
1213
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1220
1214
      return(true);
1221
1215
    }
1222
 
 
1223
1216
    key_info++;
1224
1217
  }
1225
 
 
1226
1218
  if (!unique_key && !primary_key &&
1227
1219
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1228
1220
  {
1229
1221
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1230
1222
    return(true);
1231
1223
  }
1232
 
 
1233
1224
  if (auto_increment > 0)
1234
1225
  {
1235
1226
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1240
1231
                     (qsort_cmp) sort_keys);
1241
1232
 
1242
1233
  /* Check fields. */
1243
 
  it= alter_info->create_list.begin();
 
1234
  it.rewind();
1244
1235
  while ((sql_field=it++))
1245
1236
  {
1246
1237
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1247
1238
 
1248
1239
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1249
1240
        !sql_field->def &&
1250
 
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
 
1241
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1251
1242
        (sql_field->flags & NOT_NULL_FLAG) &&
1252
1243
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1253
1244
    {
1311
1302
}
1312
1303
 
1313
1304
static bool locked_create_event(Session *session,
1314
 
                                const identifier::Table &identifier,
 
1305
                                TableIdentifier &identifier,
1315
1306
                                HA_CREATE_INFO *create_info,
1316
1307
                                message::Table &table_proto,
1317
1308
                                AlterInfo *alter_info,
1346
1337
        return error;
1347
1338
      }
1348
1339
 
1349
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1350
 
 
 
1340
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1351
1341
      return error;
1352
1342
    }
1353
1343
 
1364
1354
      /*
1365
1355
        @todo improve this error condition.
1366
1356
      */
1367
 
      if (definition::Cache::singleton().find(identifier.getKey()))
 
1357
      if (TableShare::getShare(identifier))
1368
1358
      {
1369
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1370
 
 
 
1359
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1371
1360
        return error;
1372
1361
      }
1373
1362
    }
1405
1394
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1406
1395
  {
1407
1396
    TransactionServices &transaction_services= TransactionServices::singleton();
1408
 
    transaction_services.createTable(*session, table_proto);
 
1397
    transaction_services.createTable(session, table_proto);
1409
1398
  }
1410
1399
 
1411
1400
  return false;
1418
1407
  Create a table
1419
1408
 
1420
1409
  SYNOPSIS
1421
 
    create_table_no_lock()
 
1410
    mysql_create_table_no_lock()
1422
1411
    session                     Thread object
1423
1412
    db                  Database
1424
1413
    table_name          Table name
1434
1423
 
1435
1424
    Note that this function assumes that caller already have taken
1436
1425
    name-lock on table being created or used some other way to ensure
1437
 
    that concurrent operations won't intervene. create_table()
 
1426
    that concurrent operations won't intervene. mysql_create_table()
1438
1427
    is a wrapper that can be used for this.
1439
1428
 
1440
1429
  RETURN VALUES
1442
1431
    true  error
1443
1432
*/
1444
1433
 
1445
 
bool create_table_no_lock(Session *session,
1446
 
                                const identifier::Table &identifier,
 
1434
bool mysql_create_table_no_lock(Session *session,
 
1435
                                TableIdentifier &identifier,
1447
1436
                                HA_CREATE_INFO *create_info,
1448
1437
                                message::Table &table_proto,
1449
1438
                                AlterInfo *alter_info,
1468
1457
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1469
1458
 
1470
1459
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1471
 
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1472
 
                               internal_tmp_table,
1473
 
                               &db_options,
1474
 
                               &key_info_buffer, &key_count,
1475
 
                               select_field_count))
 
1460
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1461
                                 internal_tmp_table,
 
1462
                                 &db_options,
 
1463
                                 &key_info_buffer, &key_count,
 
1464
                                 select_field_count))
1476
1465
  {
1477
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
 
1466
    boost::mutex::scoped_lock lock(LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1478
1467
    error= locked_create_event(session,
1479
1468
                               identifier,
1480
1469
                               create_info,
1495
1484
  @note the following two methods implement create [temporary] table.
1496
1485
*/
1497
1486
static bool drizzle_create_table(Session *session,
1498
 
                                 const identifier::Table &identifier,
 
1487
                                 TableIdentifier &identifier,
1499
1488
                                 HA_CREATE_INFO *create_info,
1500
1489
                                 message::Table &table_proto,
1501
1490
                                 AlterInfo *alter_info,
1522
1511
    }
1523
1512
    else
1524
1513
    {
1525
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1514
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1526
1515
      result= true;
1527
1516
    }
1528
1517
  }
1529
1518
  else
1530
1519
  {
1531
 
    result= create_table_no_lock(session,
 
1520
    result= mysql_create_table_no_lock(session,
1532
1521
                                       identifier,
1533
1522
                                       create_info,
1534
1523
                                       table_proto,
1540
1529
 
1541
1530
  if (name_lock)
1542
1531
  {
1543
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1532
    boost::mutex::scoped_lock lock(LOCK_open); /* Lock for removing name_lock during table create */
1544
1533
    session->unlink_open_table(name_lock);
1545
1534
  }
1546
1535
 
1549
1538
 
1550
1539
 
1551
1540
/*
1552
 
  Database locking aware wrapper for create_table_no_lock(),
 
1541
  Database locking aware wrapper for mysql_create_table_no_lock(),
1553
1542
*/
1554
 
bool create_table(Session *session,
1555
 
                        const identifier::Table &identifier,
 
1543
bool mysql_create_table(Session *session,
 
1544
                        TableIdentifier &identifier,
1556
1545
                        HA_CREATE_INFO *create_info,
1557
1546
                        message::Table &table_proto,
1558
1547
                        AlterInfo *alter_info,
1562
1551
{
1563
1552
  if (identifier.isTmp())
1564
1553
  {
1565
 
    return create_table_no_lock(session,
 
1554
    return mysql_create_table_no_lock(session,
1566
1555
                                      identifier,
1567
1556
                                      create_info,
1568
1557
                                      table_proto,
1632
1621
  Rename a table.
1633
1622
 
1634
1623
  SYNOPSIS
1635
 
    rename_table()
 
1624
    mysql_rename_table()
1636
1625
      session
1637
1626
      base                      The plugin::StorageEngine handle.
1638
1627
      old_db                    The old database name.
1646
1635
*/
1647
1636
 
1648
1637
bool
1649
 
rename_table(Session &session,
 
1638
mysql_rename_table(Session &session,
1650
1639
                   plugin::StorageEngine *base,
1651
 
                   const identifier::Table &from,
1652
 
                   const identifier::Table &to)
 
1640
                   TableIdentifier &from,
 
1641
                   TableIdentifier &to)
1653
1642
{
1654
1643
  int error= 0;
1655
1644
 
1669
1658
  }
1670
1659
  else if (error)
1671
1660
  {
1672
 
    std::string from_path;
1673
 
    std::string to_path;
1674
 
 
1675
 
    from.getSQLPath(from_path);
1676
 
    to.getSQLPath(to_path);
1677
 
 
1678
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1679
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
 
1661
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str();
 
1662
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str();
1680
1663
 
1681
1664
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1682
1665
  }
1700
1683
   the table is closed.
1701
1684
 
1702
1685
  PREREQUISITES
1703
 
    Lock on table::Cache::singleton().mutex()
 
1686
    Lock on LOCK_open
1704
1687
    Win32 clients must also have a WRITE LOCK on the table !
1705
1688
*/
1706
1689
 
1708
1691
                              enum ha_extra_function function)
1709
1692
{
1710
1693
 
1711
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1694
  safe_mutex_assert_owner(LOCK_open.native_handle());
1712
1695
 
1713
1696
  table->cursor->extra(function);
1714
1697
  /* Mark all tables that are in use as 'old' */
1715
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1698
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1716
1699
 
1717
1700
  /* Wait until all there are no other threads that has this table open */
1718
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1719
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
1701
  TableIdentifier identifier(table->getMutableShare()->getSchemaName(), table->getMutableShare()->getTableName());
 
1702
  remove_table_from_cache(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1720
1703
}
1721
1704
 
1722
1705
/*
1732
1715
    reopen the table.
1733
1716
 
1734
1717
  PREREQUISITES
1735
 
    Lock on table::Cache::singleton().mutex()
 
1718
    Lock on LOCK_open
1736
1719
    Win32 clients must also have a WRITE LOCK on the table !
1737
1720
*/
1738
1721
 
1743
1726
  /* Close lock if this is not got with LOCK TABLES */
1744
1727
  if (lock)
1745
1728
  {
1746
 
    unlockTables(lock);
 
1729
    mysql_unlock_tables(this, lock);
1747
1730
    lock= NULL;                 // Start locked threads
1748
1731
  }
1749
1732
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1750
1733
  unlink_open_table(table);
1751
1734
 
1752
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1753
 
  locking::broadcast_refresh();
 
1735
  /* When lock on LOCK_open is freed other threads can continue */
 
1736
  broadcast_refresh();
1754
1737
}
1755
1738
 
1756
1739
/*
1759
1742
    true  Message should be sent by caller
1760
1743
          (admin operation or network communication failed)
1761
1744
*/
1762
 
static bool admin_table(Session* session, TableList* tables,
 
1745
static bool mysql_admin_table(Session* session, TableList* tables,
1763
1746
                              HA_CHECK_OPT* check_opt,
1764
1747
                              const char *operator_name,
1765
1748
                              thr_lock_type lock_type,
1768
1751
                                                            HA_CHECK_OPT *))
1769
1752
{
1770
1753
  TableList *table;
1771
 
  Select_Lex *select= &session->getLex()->select_lex;
 
1754
  Select_Lex *select= &session->lex->select_lex;
1772
1755
  List<Item> field_list;
1773
1756
  Item *item;
 
1757
  LEX *lex= session->lex;
1774
1758
  int result_code= 0;
1775
1759
  TransactionServices &transaction_services= TransactionServices::singleton();
1776
1760
  const CHARSET_INFO * const cs= system_charset_info;
1777
1761
 
1778
1762
  if (! session->endActiveTransaction())
1779
1763
    return 1;
1780
 
 
1781
1764
  field_list.push_back(item = new Item_empty_string("Table",
1782
1765
                                                    NAME_CHAR_LEN * 2,
1783
1766
                                                    cs));
1788
1771
  item->maybe_null = 1;
1789
1772
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1790
1773
  item->maybe_null = 1;
1791
 
  if (session->getClient()->sendFields(&field_list))
 
1774
  if (session->client->sendFields(&field_list))
1792
1775
    return true;
1793
1776
 
1794
1777
  for (table= tables; table; table= table->next_local)
1795
1778
  {
1796
 
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
 
    std::string table_name;
 
1779
    char table_name[NAME_LEN*2+2];
 
1780
    char* db = table->db;
1798
1781
    bool fatal_error=0;
1799
1782
 
1800
 
    table_identifier.getSQLPath(table_name);
1801
 
 
 
1783
    snprintf(table_name, sizeof(table_name), "%s.%s",db,table->table_name);
1802
1784
    table->lock_type= lock_type;
1803
1785
    /* open only one table from local list of command */
1804
1786
    {
1813
1795
        so it have to be prepared.
1814
1796
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1815
1797
      */
1816
 
      session->getLex()->query_tables= table;
1817
 
      session->getLex()->query_tables_last= &table->next_global;
1818
 
      session->getLex()->query_tables_own_last= 0;
 
1798
      lex->query_tables= table;
 
1799
      lex->query_tables_last= &table->next_global;
 
1800
      lex->query_tables_own_last= 0;
1819
1801
      session->no_warnings_for_error= 0;
1820
1802
 
1821
1803
      session->openTablesLock(table);
1845
1827
    {
1846
1828
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1829
      uint32_t length;
1848
 
      session->getClient()->store(table_name.c_str());
1849
 
      session->getClient()->store(operator_name);
1850
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1830
      session->client->store(table_name);
 
1831
      session->client->store(operator_name);
 
1832
      session->client->store(STRING_WITH_LEN("error"));
1851
1833
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
 
                       table_name.c_str());
1853
 
      session->getClient()->store(buff, length);
1854
 
      transaction_services.autocommitOrRollback(*session, false);
 
1834
                       table_name);
 
1835
      session->client->store(buff, length);
 
1836
      transaction_services.autocommitOrRollback(session, false);
1855
1837
      session->endTransaction(COMMIT);
1856
1838
      session->close_thread_tables();
1857
 
      session->getLex()->reset_query_tables_list(false);
 
1839
      lex->reset_query_tables_list(false);
1858
1840
      table->table=0;                           // For query cache
1859
 
      if (session->getClient()->flush())
 
1841
      if (session->client->flush())
1860
1842
        goto err;
1861
1843
      continue;
1862
1844
    }
1864
1846
    /* Close all instances of the table to allow repair to rename files */
1865
1847
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1866
1848
    {
1867
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1868
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
 
1849
      LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
 
1850
      const char *old_message=session->enter_cond(COND_refresh, LOCK_open,
1869
1851
                                                  "Waiting to get writelock");
1870
 
      session->abortLock(table->table);
1871
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
1852
      mysql_lock_abort(session,table->table);
 
1853
      TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
 
1854
      remove_table_from_cache(session, identifier,
 
1855
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
1856
                              RTFC_CHECK_KILLED_FLAG);
1873
1857
      session->exit_cond(old_message);
1874
 
      if (session->getKilled())
 
1858
      if (session->killed)
1875
1859
        goto err;
1876
1860
      open_for_modify= 0;
1877
1861
    }
1880
1864
 
1881
1865
send_result:
1882
1866
 
1883
 
    session->getLex()->cleanup_after_one_table_open();
 
1867
    lex->cleanup_after_one_table_open();
1884
1868
    session->clear_error();  // these errors shouldn't get client
1885
1869
    {
1886
 
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
 
1870
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1871
      DRIZZLE_ERROR *err;
1888
1872
      while ((err= it++))
1889
1873
      {
1890
 
        session->getClient()->store(table_name.c_str());
1891
 
        session->getClient()->store(operator_name);
1892
 
        session->getClient()->store(warning_level_names[err->level].str,
 
1874
        session->client->store(table_name);
 
1875
        session->client->store(operator_name);
 
1876
        session->client->store(warning_level_names[err->level].str,
1893
1877
                               warning_level_names[err->level].length);
1894
 
        session->getClient()->store(err->msg);
1895
 
        if (session->getClient()->flush())
 
1878
        session->client->store(err->msg);
 
1879
        if (session->client->flush())
1896
1880
          goto err;
1897
1881
      }
1898
1882
      drizzle_reset_errors(session, true);
1899
1883
    }
1900
 
    session->getClient()->store(table_name.c_str());
1901
 
    session->getClient()->store(operator_name);
 
1884
    session->client->store(table_name);
 
1885
    session->client->store(operator_name);
1902
1886
 
1903
1887
    switch (result_code) {
1904
1888
    case HA_ADMIN_NOT_IMPLEMENTED:
1906
1890
        char buf[ERRMSGSIZE+20];
1907
1891
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1892
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1910
 
        session->getClient()->store(buf, length);
 
1893
        session->client->store(STRING_WITH_LEN("note"));
 
1894
        session->client->store(buf, length);
1911
1895
      }
1912
1896
      break;
1913
1897
 
1914
1898
    case HA_ADMIN_OK:
1915
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1916
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
1899
      session->client->store(STRING_WITH_LEN("status"));
 
1900
      session->client->store(STRING_WITH_LEN("OK"));
1917
1901
      break;
1918
1902
 
1919
1903
    case HA_ADMIN_FAILED:
1920
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1921
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
1904
      session->client->store(STRING_WITH_LEN("status"));
 
1905
      session->client->store(STRING_WITH_LEN("Operation failed"));
1922
1906
      break;
1923
1907
 
1924
1908
    case HA_ADMIN_REJECT:
1925
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1926
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
1909
      session->client->store(STRING_WITH_LEN("status"));
 
1910
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1927
1911
      open_for_modify= false;
1928
1912
      break;
1929
1913
 
1930
1914
    case HA_ADMIN_ALREADY_DONE:
1931
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1932
 
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
 
1915
      session->client->store(STRING_WITH_LEN("status"));
 
1916
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1933
1917
      break;
1934
1918
 
1935
1919
    case HA_ADMIN_CORRUPT:
1936
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1937
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
1920
      session->client->store(STRING_WITH_LEN("error"));
 
1921
      session->client->store(STRING_WITH_LEN("Corrupt"));
1938
1922
      fatal_error=1;
1939
1923
      break;
1940
1924
 
1941
1925
    case HA_ADMIN_INVALID:
1942
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1943
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
1926
      session->client->store(STRING_WITH_LEN("error"));
 
1927
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1944
1928
      break;
1945
1929
 
1946
1930
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1949
1933
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1950
1934
                             _("Unknown - internal error %d during operation"),
1951
1935
                             result_code);
1952
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1953
 
        session->getClient()->store(buf, length);
 
1936
        session->client->store(STRING_WITH_LEN("error"));
 
1937
        session->client->store(buf, length);
1954
1938
        fatal_error=1;
1955
1939
        break;
1956
1940
      }
1969
1953
        }
1970
1954
        else
1971
1955
        {
1972
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
1956
          boost::mutex::scoped_lock lock(LOCK_open);
 
1957
          TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
 
1958
          remove_table_from_cache(session, identifier, RTFC_NO_FLAG);
1975
1959
        }
1976
1960
      }
1977
1961
    }
1978
 
    transaction_services.autocommitOrRollback(*session, false);
 
1962
    transaction_services.autocommitOrRollback(session, false);
1979
1963
    session->endTransaction(COMMIT);
1980
1964
    session->close_thread_tables();
1981
1965
    table->table=0;                             // For query cache
1982
 
    if (session->getClient()->flush())
 
1966
    if (session->client->flush())
1983
1967
      goto err;
1984
1968
  }
1985
1969
 
1987
1971
  return(false);
1988
1972
 
1989
1973
err:
1990
 
  transaction_services.autocommitOrRollback(*session, true);
 
1974
  transaction_services.autocommitOrRollback(session, true);
1991
1975
  session->endTransaction(ROLLBACK);
1992
1976
  session->close_thread_tables();                       // Shouldn't be needed
1993
1977
  if (table)
2001
1985
    Altough exclusive name-lock on target table protects us from concurrent
2002
1986
    DML and DDL operations on it we still want to wrap .FRM creation and call
2003
1987
    to plugin::StorageEngine::createTable() in critical section protected by
2004
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
1988
    LOCK_open in order to provide minimal atomicity against operations which
2005
1989
    disregard name-locks, like I_S implementation, for example. This is a
2006
1990
    temporary and should not be copied. Instead we should fix our code to
2007
1991
    always honor name-locks.
2008
1992
 
2009
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
1993
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2010
1994
    during the call to plugin::StorageEngine::createTable().
2011
1995
    See bug #28614 for more info.
2012
1996
  */
2013
 
static bool create_table_wrapper(Session &session,
2014
 
                                 const message::Table& create_table_proto,
2015
 
                                 identifier::Table::const_reference destination_identifier,
2016
 
                                 identifier::Table::const_reference source_identifier,
 
1997
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
1998
                                 TableIdentifier &destination_identifier,
 
1999
                                 TableIdentifier &src_table,
2017
2000
                                 bool is_engine_set)
2018
2001
{
2019
 
  // We require an additional table message because during parsing we used
2020
 
  // a "new" message and it will not have all of the information that the
2021
 
  // source table message would have.
2022
 
  message::Table new_table_message;
2023
 
 
2024
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2025
 
 
2026
 
  if (not source_table_message)
2027
 
  {
2028
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2029
 
    return false;
2030
 
  }
2031
 
 
2032
 
  new_table_message.CopyFrom(*source_table_message);
 
2002
  int protoerr= EEXIST;
 
2003
  message::Table new_proto;
 
2004
  message::Table src_proto;
 
2005
 
 
2006
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
2007
                                                      src_table,
 
2008
                                                      src_proto);
 
2009
  new_proto.CopyFrom(src_proto);
2033
2010
 
2034
2011
  if (destination_identifier.isTmp())
2035
2012
  {
2036
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
2013
    new_proto.set_type(message::Table::TEMPORARY);
2037
2014
  }
2038
2015
  else
2039
2016
  {
2040
 
    new_table_message.set_type(message::Table::STANDARD);
 
2017
    new_proto.set_type(message::Table::STANDARD);
2041
2018
  }
2042
2019
 
2043
2020
  if (is_engine_set)
2044
2021
  {
2045
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
2022
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2046
2023
  }
2047
2024
 
2048
2025
  { // We now do a selective copy of elements on to the new table.
2049
 
    new_table_message.set_name(create_table_proto.name());
2050
 
    new_table_message.set_schema(create_table_proto.schema());
2051
 
    new_table_message.set_catalog(create_table_proto.catalog());
 
2026
    new_proto.set_name(create_table_proto.name());
 
2027
    new_proto.set_schema(create_table_proto.schema());
 
2028
    new_proto.set_catalog(create_table_proto.catalog());
2052
2029
  }
2053
2030
 
2054
 
  /* Fix names of foreign keys being added */
2055
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2031
  if (protoerr && protoerr != EEXIST)
2056
2032
  {
2057
 
    if (new_table_message.fk_constraint(j).has_name())
2058
 
    {
2059
 
      std::string name(new_table_message.name());
2060
 
      char number[20];
2061
 
 
2062
 
      name.append("_ibfk_");
2063
 
      snprintf(number, sizeof(number), "%d", j+1);
2064
 
      name.append(number);
2065
 
 
2066
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2067
 
      pfkey->set_name(name);
2068
 
    }
 
2033
    if (errno == ENOENT)
 
2034
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
 
2035
    else
 
2036
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
 
2037
 
 
2038
    return false;
2069
2039
  }
2070
2040
 
2071
2041
  /*
2072
2042
    As mysql_truncate don't work on a new table at this stage of
2073
 
    creation, instead create the table directly (for both normal and temporary tables).
 
2043
    creation, instead create the table directly (for both normal
 
2044
    and temporary tables).
2074
2045
  */
2075
 
  bool success= plugin::StorageEngine::createTable(session,
2076
 
                                                   destination_identifier,
2077
 
                                                   new_table_message);
 
2046
  int err= plugin::StorageEngine::createTable(session,
 
2047
                                              destination_identifier,
 
2048
                                              new_proto);
2078
2049
 
2079
 
  if (success && not destination_identifier.isTmp())
 
2050
  if (err == false && not destination_identifier.isTmp())
2080
2051
  {
2081
2052
    TransactionServices &transaction_services= TransactionServices::singleton();
2082
 
    transaction_services.createTable(session, new_table_message);
 
2053
    transaction_services.createTable(&session, new_proto);
2083
2054
  }
2084
2055
 
2085
 
  return success;
 
2056
  return err ? false : true;
2086
2057
}
2087
2058
 
2088
2059
/*
2089
2060
  Create a table identical to the specified table
2090
2061
 
2091
2062
  SYNOPSIS
2092
 
    create_like_table()
 
2063
    mysql_create_like_table()
2093
2064
    session             Thread object
2094
2065
    table       Table list element for target table
2095
2066
    src_table   Table list element for source table
2100
2071
    true  error
2101
2072
*/
2102
2073
 
2103
 
bool create_like_table(Session* session,
2104
 
                       identifier::Table::const_reference destination_identifier,
2105
 
                       identifier::Table::const_reference source_identifier,
2106
 
                       message::Table &create_table_proto,
2107
 
                       bool is_if_not_exists,
2108
 
                       bool is_engine_set)
 
2074
bool mysql_create_like_table(Session* session,
 
2075
                             TableIdentifier &destination_identifier,
 
2076
                             TableList* table, TableList* src_table,
 
2077
                             message::Table &create_table_proto,
 
2078
                             bool is_if_not_exists,
 
2079
                             bool is_engine_set)
2109
2080
{
 
2081
  char *db= table->db;
 
2082
  char *table_name= table->table_name;
2110
2083
  bool res= true;
2111
 
  bool table_exists= false;
 
2084
  uint32_t not_used;
 
2085
 
 
2086
  /*
 
2087
    By opening source table we guarantee that it exists and no concurrent
 
2088
    DDL operation will mess with it. Later we also take an exclusive
 
2089
    name-lock on target table name, which makes copying of .frm cursor,
 
2090
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2091
    against concurrent DML and DDL operations on target table.
 
2092
    Thus by holding both these "locks" we ensure that our statement is
 
2093
    properly isolated from all concurrent operations which matter.
 
2094
  */
 
2095
  if (session->open_tables_from_list(&src_table, &not_used))
 
2096
    return true;
 
2097
 
 
2098
  TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
 
2099
                                 src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
 
2100
 
 
2101
 
2112
2102
 
2113
2103
  /*
2114
2104
    Check that destination tables does not exist. Note that its name
2116
2106
 
2117
2107
    For temporary tables we don't aim to grab locks.
2118
2108
  */
 
2109
  bool table_exists= false;
2119
2110
  if (destination_identifier.isTmp())
2120
2111
  {
2121
 
    if (session->find_temporary_table(destination_identifier))
 
2112
    if (session->find_temporary_table(db, table_name))
2122
2113
    {
2123
2114
      table_exists= true;
2124
2115
    }
2125
2116
    else
2126
2117
    {
2127
 
      bool was_created= create_table_wrapper(*session,
2128
 
                                             create_table_proto,
2129
 
                                             destination_identifier,
2130
 
                                             source_identifier,
2131
 
                                             is_engine_set);
 
2118
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2119
                                             src_identifier, is_engine_set);
2132
2120
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2133
2121
      {
2134
2122
        (void) session->rm_temporary_table(destination_identifier, true);
2152
2140
    {
2153
2141
      if (name_lock)
2154
2142
      {
2155
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2143
        boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2156
2144
        session->unlink_open_table(name_lock);
2157
2145
      }
2158
2146
 
2171
2159
    {
2172
2160
      bool was_created;
2173
2161
      {
2174
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2162
        boost::mutex::scoped_lock lock(LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
2163
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
 
                                          source_identifier, is_engine_set);
 
2164
                                               src_identifier, is_engine_set);
2177
2165
      }
2178
2166
 
2179
2167
      // So we blew the creation of the table, and we scramble to clean up
2180
2168
      // anything that might have been created (read... it is a hack)
2181
2169
      if (not was_created)
2182
2170
      {
2183
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
 
2171
        quick_rm_table(*session, destination_identifier);
2184
2172
      } 
2185
2173
      else
2186
2174
      {
2190
2178
 
2191
2179
    if (name_lock)
2192
2180
    {
2193
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2181
      boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2194
2182
      session->unlink_open_table(name_lock);
2195
2183
    }
2196
2184
  }
2201
2189
    {
2202
2190
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2191
      snprintf(warn_buff, sizeof(warn_buff),
2204
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2192
               ER(ER_TABLE_EXISTS_ERROR), table_name);
2205
2193
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2207
 
      return false;
2208
 
    }
2209
 
 
2210
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2211
 
 
2212
 
    return true;
 
2194
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2195
      res= false;
 
2196
    }
 
2197
    else
 
2198
    {
 
2199
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2200
    }
2213
2201
  }
2214
2202
 
2215
 
  return res;
 
2203
  return(res);
2216
2204
}
2217
2205
 
2218
2206
 
2219
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2207
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2220
2208
{
2221
2209
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2222
2210
 
2223
 
  return(admin_table(session, tables, check_opt,
 
2211
  return(mysql_admin_table(session, tables, check_opt,
2224
2212
                                "analyze", lock_type, true,
2225
2213
                                &Cursor::ha_analyze));
2226
2214
}
2227
2215
 
2228
2216
 
2229
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2217
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2230
2218
{
2231
2219
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2232
2220
 
2233
 
  return(admin_table(session, tables, check_opt,
 
2221
  return(mysql_admin_table(session, tables, check_opt,
2234
2222
                                "check", lock_type,
2235
2223
                                false,
2236
2224
                                &Cursor::ha_check));