~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2010-04-22 02:46:23 UTC
  • mto: (1497.3.4 enable-dtrace)
  • mto: This revision was merged to the branch mainline in revision 1527.
  • Revision ID: mordred@inaugust.com-20100422024623-4urw8fi8eraci08p
Don't overwrite the pandora_vc_revinfo file if we don't have new
authoratative information.

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
 
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 pid_t current_pid;
 
58
 
 
59
bool is_primary_key(KEY *key_info)
63
60
{
64
61
  static const char * primary_key_name="PRIMARY";
65
62
  return (strcmp(key_info->name, primary_key_name)==0);
74
71
    return NULL;
75
72
}
76
73
 
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);
 
74
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
75
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
79
76
 
80
77
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
78
 
86
83
    let's fetch the database default character set and
87
84
    apply it to the table.
88
85
  */
89
 
  identifier::Schema identifier(db);
 
86
  SchemaIdentifier identifier(db);
90
87
  if (create_info->default_table_charset == NULL)
91
88
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
92
89
}
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
  TransactionServices &transaction_services= TransactionServices::singleton();
 
110
  transaction_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
  TransactionServices &transaction_services= TransactionServices::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
  transaction_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
    TableIdentifier identifier(table->db, table->table_name);
 
183
    TableShare *share;
 
184
    table->db_type= NULL;
 
185
 
 
186
    if ((share= TableShare::getShare(identifier)))
 
187
    {
 
188
      table->db_type= share->db_type();
 
189
    }
 
190
  }
 
191
 
 
192
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
193
  {
 
194
    pthread_mutex_unlock(&LOCK_open);
 
195
    return 1;
 
196
  }
 
197
 
 
198
  /* Don't give warnings for not found errors, as we already generate notes */
 
199
  session->no_warnings_for_error= 1;
 
200
 
 
201
  for (table= tables; table; table= table->next_local)
 
202
  {
 
203
    char *db=table->db;
 
204
 
 
205
    error= session->drop_temporary_table(table);
 
206
 
 
207
    switch (error) {
 
208
    case  0:
 
209
      // removed temporary table
 
210
      continue;
 
211
    case -1:
 
212
      error= 1;
 
213
      goto err_with_placeholders;
 
214
    default:
 
215
      // temporary table not found
 
216
      error= 0;
 
217
    }
 
218
 
 
219
    if (drop_temporary == false)
 
220
    {
 
221
      Table *locked_table;
 
222
      abort_locked_tables(session, db, table->table_name);
 
223
      remove_table_from_cache(session, db, table->table_name,
 
224
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
225
                              RTFC_CHECK_KILLED_FLAG);
 
226
      /*
 
227
        If the table was used in lock tables, remember it so that
 
228
        unlock_table_names can free it
 
229
      */
 
230
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
231
        table->table= locked_table;
 
232
 
 
233
      if (session->killed)
 
234
      {
 
235
        error= -1;
 
236
        goto err_with_placeholders;
 
237
      }
 
238
    }
 
239
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? message::Table::INTERNAL : message::Table::STANDARD);
 
240
 
 
241
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
242
    {
 
243
      // Table was not found on disk and table can't be created from engine
 
244
      if (if_exists)
 
245
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
246
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
247
                            table->table_name);
 
248
      else
173
249
        error= 1;
174
 
        break;
175
 
      default:
176
 
        // temporary table not found
 
250
    }
 
251
    else
 
252
    {
 
253
      error= plugin::StorageEngine::dropTable(*session, identifier);
 
254
 
 
255
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
256
      {
177
257
        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);
 
258
        session->clear_error();
 
259
      }
 
260
 
 
261
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
262
      {
 
263
        /* the table is referenced by a foreign key constraint */
 
264
        foreign_key_error= true;
 
265
      }
 
266
    }
 
267
 
 
268
    if (error == 0 || (if_exists && foreign_key_error == false))
 
269
    {
 
270
      TransactionServices &transaction_services= TransactionServices::singleton();
 
271
      transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
 
272
    }
 
273
 
 
274
    if (error)
 
275
    {
 
276
      if (wrong_tables.length())
 
277
        wrong_tables.append(',');
 
278
      wrong_tables.append(String(table->table_name,system_charset_info));
 
279
    }
 
280
  }
 
281
  /*
 
282
    It's safe to unlock LOCK_open: we have an exclusive lock
 
283
    on the table name.
 
284
  */
 
285
  pthread_mutex_unlock(&LOCK_open);
 
286
  error= 0;
252
287
 
253
288
  if (wrong_tables.length())
254
289
  {
264
299
    error= 1;
265
300
  }
266
301
 
 
302
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
 
303
 
 
304
err_with_placeholders:
 
305
  unlock_table_names(tables, NULL);
 
306
  pthread_mutex_unlock(&LOCK_open);
267
307
  session->no_warnings_for_error= 0;
268
308
 
269
309
  return error;
270
310
}
271
311
 
 
312
 
 
313
/*
 
314
  Quickly remove a table.
 
315
 
 
316
  SYNOPSIS
 
317
    quick_rm_table()
 
318
      base                      The plugin::StorageEngine handle.
 
319
      db                        The database name.
 
320
      table_name                The table name.
 
321
      is_tmp                    If the table is temp.
 
322
 
 
323
  RETURN
 
324
    0           OK
 
325
    != 0        Error
 
326
*/
 
327
bool quick_rm_table(Session& session,
 
328
                    TableIdentifier &identifier)
 
329
{
 
330
  return (plugin::StorageEngine::dropTable(session, identifier));
 
331
}
 
332
 
272
333
/*
273
334
  Sort keys in the following order:
274
335
  - PRIMARY KEY
282
343
  PRIMARY keys are prioritized.
283
344
*/
284
345
 
285
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
346
static int sort_keys(KEY *a, KEY *b)
286
347
{
287
348
  ulong a_flags= a->flags, b_flags= b->flags;
288
349
 
334
395
    1             Error
335
396
*/
336
397
 
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
398
static bool check_duplicates_in_interval(const char *set_or_name,
372
399
                                         const char *name, TYPELIB *typelib,
373
400
                                         const CHARSET_INFO * const cs,
378
405
  unsigned int *cur_length= typelib->type_lengths;
379
406
  *dup_val_count= 0;
380
407
 
381
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
382
 
 
383
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
408
  for ( ; tmp.count > 1; cur_value++, cur_length++)
384
409
  {
385
410
    tmp.type_names++;
386
411
    tmp.type_lengths++;
387
412
    tmp.count--;
388
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
413
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
389
414
    {
390
415
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
416
               name,*cur_value,set_or_name);
392
417
      return 1;
393
418
    }
394
 
    else
395
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
396
419
  }
397
420
  return 0;
398
421
}
465
488
 
466
489
  switch (sql_field->sql_type) {
467
490
  case DRIZZLE_TYPE_BLOB:
 
491
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
468
492
    sql_field->length= 8; // Unireg field length
469
493
    (*blob_columns)++;
470
494
    break;
471
 
 
 
495
  case DRIZZLE_TYPE_VARCHAR:
 
496
    sql_field->pack_flag=0;
 
497
    break;
472
498
  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:
 
499
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
 
500
    if (check_duplicates_in_interval("ENUM",
 
501
                                     sql_field->field_name,
 
502
                                     sql_field->interval,
 
503
                                     sql_field->charset,
 
504
                                     &dup_val_count))
 
505
      return 1;
 
506
    break;
 
507
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
508
  case DRIZZLE_TYPE_DATETIME:
 
509
  case DRIZZLE_TYPE_NULL:
 
510
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
 
511
    break;
 
512
  case DRIZZLE_TYPE_DECIMAL:
 
513
    sql_field->pack_flag= 0;
 
514
    break;
486
515
  case DRIZZLE_TYPE_TIMESTAMP:
487
516
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
517
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
493
522
        (*timestamps_with_niladic)++;
494
523
      }
495
524
      else
496
 
      {
497
525
        sql_field->unireg_check= Field::NONE;
498
 
      }
499
526
    }
500
527
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
528
      (*timestamps_with_niladic)++;
503
 
    }
504
529
 
505
530
    (*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:
 
531
    /* fall-through */
 
532
  default:
 
533
    sql_field->pack_flag=(0 |
 
534
                          f_settype((uint32_t) sql_field->sql_type));
520
535
    break;
521
536
  }
522
 
 
523
537
  return 0;
524
538
}
525
539
 
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)
 
540
static int mysql_prepare_create_table(Session *session,
 
541
                                      HA_CREATE_INFO *create_info,
 
542
                                      message::Table &create_proto,
 
543
                                      AlterInfo *alter_info,
 
544
                                      bool tmp_table,
 
545
                                      uint32_t *db_options,
 
546
                                      KEY **key_info_buffer,
 
547
                                      uint32_t *key_count,
 
548
                                      int select_field_count)
535
549
{
536
550
  const char    *key_name;
537
551
  CreateField   *sql_field,*dup_field;
538
552
  uint          field,null_fields,blob_columns,max_key_length;
539
553
  ulong         record_offset= 0;
540
 
  KeyInfo               *key_info;
541
 
  KeyPartInfo *key_part_info;
 
554
  KEY           *key_info;
 
555
  KEY_PART_INFO *key_part_info;
542
556
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
557
  int           field_no,dup_no;
544
558
  int           select_field_pos,auto_increment=0;
545
559
  List_iterator<CreateField> it(alter_info->create_list);
546
560
  List_iterator<CreateField> it2(alter_info->create_list);
552
566
  null_fields=blob_columns=0;
553
567
  max_key_length= engine->max_key_length();
554
568
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
569
  for (field_no=0; (sql_field=it++) ; field_no++)
556
570
  {
557
571
    const CHARSET_INFO *save_cs;
558
572
 
562
576
      executing a prepared statement for the second time.
563
577
    */
564
578
    sql_field->length= sql_field->char_length;
565
 
 
566
579
    if (!sql_field->charset)
567
580
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
581
    /*
570
582
      table_charset is set in ALTER Table if we want change character set
571
583
      for all varchar/char columns.
618
630
 
619
631
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
632
    {
621
 
      size_t dummy;
 
633
      uint32_t dummy;
622
634
      const CHARSET_INFO * const cs= sql_field->charset;
623
635
      TYPELIB *interval= sql_field->interval;
624
636
 
651
663
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
664
                                       cs, &dummy))
653
665
          {
654
 
            size_t cnv_errs;
 
666
            uint32_t cnv_errs;
655
667
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
656
668
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
657
669
            interval->type_lengths[i]= conv.length();
693
705
            }
694
706
          }
695
707
        }
696
 
        uint32_t new_dummy;
697
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
708
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
698
709
        sql_field->length= field_length;
699
710
      }
700
711
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
762
773
    /** @todo Get rid of this MyISAM-specific crap. */
763
774
    if (not create_proto.engine().name().compare("MyISAM") &&
764
775
        ((sql_field->flags & BLOB_FLAG) ||
765
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
766
 
    {
 
776
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED)))
767
777
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
778
    it2.rewind();
771
779
  }
772
780
 
833
841
      fk_key_count++;
834
842
      if (((Foreign_key *)key)->validate(alter_info->create_list))
835
843
        return true;
836
 
 
837
844
      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
845
      if (fk_key->ref_columns.elements &&
849
846
          fk_key->ref_columns.elements != fk_key->columns.elements)
850
847
      {
879
876
             key2->name.str != ignore_key &&
880
877
             !foreign_key_prefix(key, key2)))
881
878
        {
882
 
          /* @todo issue warning message */
 
879
          /* TODO: issue warning message */
883
880
          /* mark that the generated key should be ignored */
884
881
          if (!key2->generated ||
885
882
              (key->generated && key->columns.elements <
913
910
    return(true);
914
911
  }
915
912
 
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);
 
913
  (*key_info_buffer)= key_info= (KEY*) memory::sql_calloc(sizeof(KEY) * (*key_count));
 
914
  key_part_info=(KEY_PART_INFO*) memory::sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
918
915
  if (!*key_info_buffer || ! key_part_info)
919
916
    return(true);                               // Out of memory
920
917
 
954
951
    key_info->usable_key_parts= key_number;
955
952
    key_info->algorithm= key->key_create_info.algorithm;
956
953
 
 
954
    /* Take block size from key part or table part */
 
955
    /*
 
956
      TODO: Add warning if block size changes. We can't do it here, as
 
957
      this may depend on the size of the key
 
958
    */
 
959
    key_info->block_size= (key->key_create_info.block_size ?
 
960
                           key->key_create_info.block_size :
 
961
                           create_proto.options().key_block_size());
 
962
 
 
963
    if (key_info->block_size)
 
964
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
965
 
957
966
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
958
967
                                           key->key_create_info.comment.str,
959
968
                                           key->key_create_info.comment.str +
990
999
             my_strcasecmp(system_charset_info,
991
1000
                           column->field_name.str,
992
1001
                           sql_field->field_name))
993
 
      {
994
1002
        field++;
995
 
      }
996
 
 
997
1003
      if (!sql_field)
998
1004
      {
999
1005
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
1006
        return(true);
1001
1007
      }
1002
 
 
1003
1008
      while ((dup_column= cols2++) != column)
1004
1009
      {
1005
1010
        if (!my_strcasecmp(system_charset_info,
1032
1037
            return true;
1033
1038
          }
1034
1039
        }
1035
 
 
1036
1040
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
1041
        {
1038
1042
          if (key->type == Key::PRIMARY)
1045
1049
            {
1046
1050
              message::Table::Field::FieldConstraints *constraints;
1047
1051
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
 
1052
              constraints->set_is_nullable(false);
1049
1053
            }
1050
1054
 
1051
1055
          }
1059
1063
            }
1060
1064
          }
1061
1065
        }
1062
 
 
1063
1066
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
1067
        {
1065
1068
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1069
1072
 
1070
1073
      key_part_info->fieldnr= field;
1071
1074
      key_part_info->offset=  (uint16_t) sql_field->offset;
1072
 
      key_part_info->key_type= 0;
 
1075
      key_part_info->key_type=sql_field->pack_flag;
1073
1076
      length= sql_field->key_length;
1074
1077
 
1075
1078
      if (column->length)
1137
1140
      key_part_info->length=(uint16_t) length;
1138
1141
      /* Use packed keys for long strings on the first column */
1139
1142
      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)))
 
1143
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1144
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1145
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1143
1146
      {
1144
1147
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1145
1148
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1146
 
        {
1147
1149
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1148
 
        }
1149
1150
        else
1150
 
        {
1151
1151
          key_info->flags|= HA_PACK_KEY;
1152
 
        }
1153
1152
      }
1154
1153
      /* Check if the key segment is partial, set the key flag accordingly */
1155
1154
      if (length != sql_field->key_length)
1184
1183
        key_info->name=(char*) key_name;
1185
1184
      }
1186
1185
    }
1187
 
 
1188
1186
    if (!key_info->name || check_column_name(key_info->name))
1189
1187
    {
1190
1188
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1189
      return(true);
1192
1190
    }
1193
 
 
1194
1191
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1192
      unique_key=1;
1197
 
    }
1198
 
 
1199
1193
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1194
    if (key_length > max_key_length)
1202
1195
    {
1203
1196
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1197
      return(true);
1205
1198
    }
1206
 
 
1207
1199
    key_info++;
1208
1200
  }
1209
 
 
1210
1201
  if (!unique_key && !primary_key &&
1211
1202
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1212
1203
  {
1213
1204
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1205
    return(true);
1215
1206
  }
1216
 
 
1217
1207
  if (auto_increment > 0)
1218
1208
  {
1219
1209
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1220
1210
    return(true);
1221
1211
  }
1222
1212
  /* Sort keys in optimized order */
1223
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
 
1213
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1224
1214
                     (qsort_cmp) sort_keys);
1225
1215
 
1226
1216
  /* Check fields. */
1295
1285
}
1296
1286
 
1297
1287
static bool locked_create_event(Session *session,
1298
 
                                const identifier::Table &identifier,
 
1288
                                TableIdentifier &identifier,
1299
1289
                                HA_CREATE_INFO *create_info,
1300
1290
                                message::Table &table_proto,
1301
1291
                                AlterInfo *alter_info,
1303
1293
                                bool internal_tmp_table,
1304
1294
                                uint db_options,
1305
1295
                                uint key_count,
1306
 
                                KeyInfo *key_info_buffer)
 
1296
                                KEY *key_info_buffer)
1307
1297
{
1308
1298
  bool error= true;
1309
1299
 
1330
1320
        return error;
1331
1321
      }
1332
1322
 
1333
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1334
 
 
 
1323
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1335
1324
      return error;
1336
1325
    }
1337
1326
 
1348
1337
      /*
1349
1338
        @todo improve this error condition.
1350
1339
      */
1351
 
      if (definition::Cache::singleton().find(identifier.getKey()))
 
1340
      if (TableShare::getShare(identifier))
1352
1341
      {
1353
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
 
 
 
1342
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1355
1343
        return error;
1356
1344
      }
1357
1345
    }
1389
1377
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1390
1378
  {
1391
1379
    TransactionServices &transaction_services= TransactionServices::singleton();
1392
 
    transaction_services.createTable(*session, table_proto);
 
1380
    transaction_services.createTable(session, table_proto);
1393
1381
  }
1394
1382
 
1395
1383
  return false;
1402
1390
  Create a table
1403
1391
 
1404
1392
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1393
    mysql_create_table_no_lock()
1406
1394
    session                     Thread object
1407
1395
    db                  Database
1408
1396
    table_name          Table name
1418
1406
 
1419
1407
    Note that this function assumes that caller already have taken
1420
1408
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1409
    that concurrent operations won't intervene. mysql_create_table()
1422
1410
    is a wrapper that can be used for this.
1423
1411
 
1424
1412
  RETURN VALUES
1426
1414
    true  error
1427
1415
*/
1428
1416
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1417
bool mysql_create_table_no_lock(Session *session,
 
1418
                                TableIdentifier &identifier,
1431
1419
                                HA_CREATE_INFO *create_info,
1432
1420
                                message::Table &table_proto,
1433
1421
                                AlterInfo *alter_info,
1436
1424
                                bool is_if_not_exists)
1437
1425
{
1438
1426
  uint          db_options, key_count;
1439
 
  KeyInfo               *key_info_buffer;
 
1427
  KEY           *key_info_buffer;
1440
1428
  bool          error= true;
 
1429
  TableShare share;
1441
1430
 
1442
1431
  /* Check for duplicate fields and check type of table to create */
1443
1432
  if (not alter_info->create_list.elements)
1449
1438
  assert(identifier.getTableName() == table_proto.name());
1450
1439
  db_options= create_info->table_options;
1451
1440
 
 
1441
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1442
    db_options|=HA_OPTION_PACK_RECORD;
 
1443
 
1452
1444
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1453
1445
 
1454
1446
  /* 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))
 
1447
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1448
                                 internal_tmp_table,
 
1449
                                 &db_options,
 
1450
                                 &key_info_buffer, &key_count,
 
1451
                                 select_field_count))
1460
1452
  {
1461
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
 
1453
    pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1462
1454
    error= locked_create_event(session,
1463
1455
                               identifier,
1464
1456
                               create_info,
1468
1460
                               internal_tmp_table,
1469
1461
                               db_options, key_count,
1470
1462
                               key_info_buffer);
 
1463
    pthread_mutex_unlock(&LOCK_open);
1471
1464
  }
1472
1465
 
1473
1466
  session->set_proc_info("After create");
1479
1472
  @note the following two methods implement create [temporary] table.
1480
1473
*/
1481
1474
static bool drizzle_create_table(Session *session,
1482
 
                                 const identifier::Table &identifier,
 
1475
                                 TableIdentifier &identifier,
1483
1476
                                 HA_CREATE_INFO *create_info,
1484
1477
                                 message::Table &table_proto,
1485
1478
                                 AlterInfo *alter_info,
1506
1499
    }
1507
1500
    else
1508
1501
    {
1509
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1502
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1510
1503
      result= true;
1511
1504
    }
1512
1505
  }
1513
1506
  else
1514
1507
  {
1515
 
    result= create_table_no_lock(session,
 
1508
    result= mysql_create_table_no_lock(session,
1516
1509
                                       identifier,
1517
1510
                                       create_info,
1518
1511
                                       table_proto,
1524
1517
 
1525
1518
  if (name_lock)
1526
1519
  {
1527
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1520
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1528
1521
    session->unlink_open_table(name_lock);
 
1522
    pthread_mutex_unlock(&LOCK_open);
1529
1523
  }
1530
1524
 
1531
1525
  return(result);
1533
1527
 
1534
1528
 
1535
1529
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
 
1530
  Database locking aware wrapper for mysql_create_table_no_lock(),
1537
1531
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
 
1532
bool mysql_create_table(Session *session,
 
1533
                        TableIdentifier &identifier,
1540
1534
                        HA_CREATE_INFO *create_info,
1541
1535
                        message::Table &table_proto,
1542
1536
                        AlterInfo *alter_info,
1546
1540
{
1547
1541
  if (identifier.isTmp())
1548
1542
  {
1549
 
    return create_table_no_lock(session,
 
1543
    return mysql_create_table_no_lock(session,
1550
1544
                                      identifier,
1551
1545
                                      create_info,
1552
1546
                                      table_proto,
1572
1566
**/
1573
1567
 
1574
1568
static bool
1575
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1569
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1576
1570
{
1577
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1571
  for (KEY *key=start ; key != end ; key++)
1578
1572
    if (!my_strcasecmp(system_charset_info,name,key->name))
1579
1573
      return 1;
1580
1574
  return 0;
1582
1576
 
1583
1577
 
1584
1578
static char *
1585
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1579
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1586
1580
{
1587
1581
  char buff[MAX_FIELD_NAME],*buff_end;
1588
1582
 
1616
1610
  Rename a table.
1617
1611
 
1618
1612
  SYNOPSIS
1619
 
    rename_table()
1620
 
      session
 
1613
    mysql_rename_table()
1621
1614
      base                      The plugin::StorageEngine handle.
1622
1615
      old_db                    The old database name.
1623
1616
      old_name                  The old table name.
1630
1623
*/
1631
1624
 
1632
1625
bool
1633
 
rename_table(Session &session,
1634
 
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1626
mysql_rename_table(plugin::StorageEngine *base,
 
1627
                   TableIdentifier &from,
 
1628
                   TableIdentifier &to)
1637
1629
{
 
1630
  Session *session= current_session;
1638
1631
  int error= 0;
1639
1632
 
1640
1633
  assert(base);
1645
1638
    return true;
1646
1639
  }
1647
1640
 
1648
 
  error= base->renameTable(session, from, to);
 
1641
  error= base->renameTable(*session, from, to);
1649
1642
 
1650
1643
  if (error == HA_ERR_WRONG_COMMAND)
1651
1644
  {
1653
1646
  }
1654
1647
  else if (error)
1655
1648
  {
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();
 
1649
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str();
 
1650
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str();
1664
1651
 
1665
1652
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1666
1653
  }
1684
1671
   the table is closed.
1685
1672
 
1686
1673
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
1674
    Lock on LOCK_open
1688
1675
    Win32 clients must also have a WRITE LOCK on the table !
1689
1676
*/
1690
1677
 
1692
1679
                              enum ha_extra_function function)
1693
1680
{
1694
1681
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1682
  safe_mutex_assert_owner(&LOCK_open);
1696
1683
 
1697
1684
  table->cursor->extra(function);
1698
1685
  /* Mark all tables that are in use as 'old' */
1699
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1686
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1700
1687
 
1701
1688
  /* 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);
 
1689
  remove_table_from_cache(session, table->s->getSchemaName(),
 
1690
                          table->s->table_name.str,
 
1691
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1692
}
1705
1693
 
1706
1694
/*
1716
1704
    reopen the table.
1717
1705
 
1718
1706
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
1707
    Lock on LOCK_open
1720
1708
    Win32 clients must also have a WRITE LOCK on the table !
1721
1709
*/
1722
1710
 
1727
1715
  /* Close lock if this is not got with LOCK TABLES */
1728
1716
  if (lock)
1729
1717
  {
1730
 
    unlockTables(lock);
 
1718
    mysql_unlock_tables(this, lock);
1731
1719
    lock= NULL;                 // Start locked threads
1732
1720
  }
1733
1721
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
1722
  unlink_open_table(table);
1735
1723
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1737
 
  locking::broadcast_refresh();
 
1724
  /* When lock on LOCK_open is freed other threads can continue */
 
1725
  broadcast_refresh();
1738
1726
}
1739
1727
 
1740
1728
/*
1743
1731
    true  Message should be sent by caller
1744
1732
          (admin operation or network communication failed)
1745
1733
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
1734
static bool mysql_admin_table(Session* session, TableList* tables,
1747
1735
                              HA_CHECK_OPT* check_opt,
1748
1736
                              const char *operator_name,
1749
1737
                              thr_lock_type lock_type,
1772
1760
  item->maybe_null = 1;
1773
1761
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
1762
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
1763
  if (session->client->sendFields(&field_list))
1776
1764
    return true;
1777
1765
 
1778
1766
  for (table= tables; table; table= table->next_local)
1779
1767
  {
1780
1768
    char table_name[NAME_LEN*2+2];
 
1769
    char* db = table->db;
1781
1770
    bool fatal_error=0;
1782
1771
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
1772
    snprintf(table_name, sizeof(table_name), "%s.%s",db,table->table_name);
1784
1773
    table->lock_type= lock_type;
1785
1774
    /* open only one table from local list of command */
1786
1775
    {
1793
1782
      /*
1794
1783
        Time zone tables and SP tables can be add to lex->query_tables list,
1795
1784
        so it have to be prepared.
1796
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
1785
        TODO: Investigate if we can put extra tables into argument instead of
 
1786
        using lex->query_tables
1797
1787
      */
1798
1788
      lex->query_tables= table;
1799
1789
      lex->query_tables_last= &table->next_global;
1827
1817
    {
1828
1818
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1819
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1820
      session->client->store(table_name);
 
1821
      session->client->store(operator_name);
 
1822
      session->client->store(STRING_WITH_LEN("error"));
1833
1823
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
1824
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
1825
      session->client->store(buff, length);
 
1826
      transaction_services.autocommitOrRollback(session, false);
1837
1827
      session->endTransaction(COMMIT);
1838
1828
      session->close_thread_tables();
1839
1829
      lex->reset_query_tables_list(false);
1840
1830
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
1831
      if (session->client->flush())
1842
1832
        goto err;
1843
1833
      continue;
1844
1834
    }
1845
1835
 
1846
1836
    /* Close all instances of the table to allow repair to rename files */
1847
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
1837
    if (lock_type == TL_WRITE && table->table->s->version)
1848
1838
    {
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);
 
1839
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
1840
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
1841
                                              "Waiting to get writelock");
 
1842
      mysql_lock_abort(session,table->table);
 
1843
      remove_table_from_cache(session, table->table->s->getSchemaName(),
 
1844
                              table->table->s->table_name.str,
 
1845
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
1846
                              RTFC_CHECK_KILLED_FLAG);
1855
1847
      session->exit_cond(old_message);
1856
 
      if (session->getKilled())
 
1848
      if (session->killed)
1857
1849
        goto err;
1858
1850
      open_for_modify= 0;
1859
1851
    }
1869
1861
      DRIZZLE_ERROR *err;
1870
1862
      while ((err= it++))
1871
1863
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
1864
        session->client->store(table_name);
 
1865
        session->client->store(operator_name);
 
1866
        session->client->store(warning_level_names[err->level].str,
1875
1867
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
1868
        session->client->store(err->msg);
 
1869
        if (session->client->flush())
1878
1870
          goto err;
1879
1871
      }
1880
1872
      drizzle_reset_errors(session, true);
1881
1873
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
1874
    session->client->store(table_name);
 
1875
    session->client->store(operator_name);
1884
1876
 
1885
1877
    switch (result_code) {
1886
1878
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
1880
        char buf[ERRMSGSIZE+20];
1889
1881
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
1882
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
1883
        session->client->store(STRING_WITH_LEN("note"));
 
1884
        session->client->store(buf, length);
1893
1885
      }
1894
1886
      break;
1895
1887
 
1896
1888
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
1889
      session->client->store(STRING_WITH_LEN("status"));
 
1890
      session->client->store(STRING_WITH_LEN("OK"));
1899
1891
      break;
1900
1892
 
1901
1893
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
1894
      session->client->store(STRING_WITH_LEN("status"));
 
1895
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
1896
      break;
1905
1897
 
1906
1898
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
1899
      session->client->store(STRING_WITH_LEN("status"));
 
1900
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
1901
      open_for_modify= false;
1910
1902
      break;
1911
1903
 
1912
1904
    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"));
 
1905
      session->client->store(STRING_WITH_LEN("status"));
 
1906
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
1907
      break;
1916
1908
 
1917
1909
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
1910
      session->client->store(STRING_WITH_LEN("error"));
 
1911
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
1912
      fatal_error=1;
1921
1913
      break;
1922
1914
 
1923
1915
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
1916
      session->client->store(STRING_WITH_LEN("error"));
 
1917
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1926
1918
      break;
1927
1919
 
1928
1920
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1931
1923
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
1924
                             _("Unknown - internal error %d during operation"),
1933
1925
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
1926
        session->client->store(STRING_WITH_LEN("error"));
 
1927
        session->client->store(buf, length);
1936
1928
        fatal_error=1;
1937
1929
        break;
1938
1930
      }
1940
1932
    if (table->table)
1941
1933
    {
1942
1934
      if (fatal_error)
1943
 
      {
1944
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1945
 
      }
 
1935
        table->table->s->version=0;               // Force close of table
1946
1936
      else if (open_for_modify)
1947
1937
      {
1948
 
        if (table->table->getShare()->getType())
1949
 
        {
 
1938
        if (table->table->s->tmp_table)
1950
1939
          table->table->cursor->info(HA_STATUS_CONST);
1951
 
        }
1952
1940
        else
1953
1941
        {
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);
 
1942
          pthread_mutex_lock(&LOCK_open);
 
1943
          remove_table_from_cache(session, table->table->s->getSchemaName(),
 
1944
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
1945
          pthread_mutex_unlock(&LOCK_open);
1957
1946
        }
1958
1947
      }
1959
1948
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
1949
    transaction_services.autocommitOrRollback(session, false);
1961
1950
    session->endTransaction(COMMIT);
1962
1951
    session->close_thread_tables();
1963
1952
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
1953
    if (session->client->flush())
1965
1954
      goto err;
1966
1955
  }
1967
1956
 
1969
1958
  return(false);
1970
1959
 
1971
1960
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
1961
  transaction_services.autocommitOrRollback(session, true);
1973
1962
  session->endTransaction(ROLLBACK);
1974
1963
  session->close_thread_tables();                       // Shouldn't be needed
1975
1964
  if (table)
1977
1966
  return(true);
1978
1967
}
1979
1968
 
 
1969
/*
 
1970
  We have to write the query before we unlock the named table.
 
1971
 
 
1972
  Since temporary tables are not replicated under row-based
 
1973
  replication, CREATE TABLE ... LIKE ... needs special
 
1974
  treatement.  We have four cases to consider, according to the
 
1975
  following decision table:
 
1976
 
 
1977
  ==== ========= ========= ==============================
 
1978
  Case    Target    Source Write to binary log
 
1979
  ==== ========= ========= ==============================
 
1980
  1       normal    normal Original statement
 
1981
  2       normal temporary Generated statement
 
1982
  3    temporary    normal Nothing
 
1983
  4    temporary temporary Nothing
 
1984
  ==== ========= ========= ==============================
 
1985
*/
 
1986
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
 
1987
                                     bool is_src_table_tmp, bool is_if_not_exists)
 
1988
{
 
1989
  if (is_src_table_tmp)
 
1990
  {
 
1991
    char buf[2048];
 
1992
    String query(buf, sizeof(buf), system_charset_info);
 
1993
    query.length(0);  // Have to zero it since constructor doesn't
 
1994
 
 
1995
 
 
1996
    /*
 
1997
      Here we open the destination table, on which we already have
 
1998
      name-lock. This is needed for store_create_info() to work.
 
1999
      The table will be closed by unlink_open_table() at the end
 
2000
      of this function.
 
2001
    */
 
2002
    table->table= name_lock;
 
2003
    pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2004
    if (session->reopen_name_locked_table(table, false))
 
2005
    {
 
2006
      pthread_mutex_unlock(&LOCK_open);
 
2007
      return false;
 
2008
    }
 
2009
    pthread_mutex_unlock(&LOCK_open);
 
2010
 
 
2011
    int result= store_create_info(table, &query, is_if_not_exists);
 
2012
 
 
2013
    assert(result == 0); // store_create_info() always return 0
 
2014
    write_bin_log(session, query.ptr());
 
2015
  }
 
2016
  else                                      // Case 1
 
2017
  {
 
2018
    write_bin_log(session, session->query.c_str());
 
2019
  }
 
2020
 
 
2021
  return true;
 
2022
}
 
2023
 
1980
2024
  /*
1981
2025
    Create a new table by copying from source table
1982
2026
 
1983
2027
    Altough exclusive name-lock on target table protects us from concurrent
1984
2028
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2029
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
2030
    LOCK_open in order to provide minimal atomicity against operations which
1987
2031
    disregard name-locks, like I_S implementation, for example. This is a
1988
2032
    temporary and should not be copied. Instead we should fix our code to
1989
2033
    always honor name-locks.
1990
2034
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
2035
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2036
    during the call to plugin::StorageEngine::createTable().
1993
2037
    See bug #28614 for more info.
1994
2038
  */
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,
 
2039
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
2040
                                 TableIdentifier &destination_identifier,
 
2041
                                 TableIdentifier &src_table,
1999
2042
                                 bool is_engine_set)
2000
2043
{
2001
 
  // We require an additional table message because during parsing we used
2002
 
  // a "new" message and it will not have all of the information that the
2003
 
  // source table message would have.
2004
 
  message::Table new_table_message;
2005
 
  drizzled::error_t error;
2006
 
 
2007
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2008
 
 
2009
 
  if (not source_table_message)
2010
 
  {
2011
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  new_table_message.CopyFrom(*source_table_message);
 
2044
  int protoerr= EEXIST;
 
2045
  message::Table new_proto;
 
2046
  message::Table src_proto;
 
2047
 
 
2048
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
2049
                                                      src_table,
 
2050
                                                      src_proto);
 
2051
  new_proto.CopyFrom(src_proto);
2016
2052
 
2017
2053
  if (destination_identifier.isTmp())
2018
2054
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
2055
    new_proto.set_type(message::Table::TEMPORARY);
2020
2056
  }
2021
2057
  else
2022
2058
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
 
2059
    new_proto.set_type(message::Table::STANDARD);
2024
2060
  }
2025
2061
 
2026
2062
  if (is_engine_set)
2027
2063
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
2064
    message::Table::StorageEngine *protoengine;
 
2065
 
 
2066
    protoengine= new_proto.mutable_engine();
 
2067
    protoengine->set_name(create_table_proto.engine().name());
2029
2068
  }
2030
2069
 
2031
2070
  { // 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());
 
2071
    new_proto.set_name(create_table_proto.name());
 
2072
    new_proto.set_schema(create_table_proto.schema());
 
2073
    new_proto.set_catalog(create_table_proto.catalog());
2035
2074
  }
2036
2075
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2076
  if (protoerr && protoerr != EEXIST)
2039
2077
  {
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
 
    }
 
2078
    if (errno == ENOENT)
 
2079
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
 
2080
    else
 
2081
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
 
2082
 
 
2083
    return false;
2052
2084
  }
2053
2085
 
2054
2086
  /*
2055
2087
    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).
 
2088
    creation, instead create the table directly (for both normal
 
2089
    and temporary tables).
2057
2090
  */
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;
 
2091
  int err= plugin::StorageEngine::createTable(session,
 
2092
                                              destination_identifier,
 
2093
                                              true, new_proto);
 
2094
 
 
2095
  return err ? false : true;
2069
2096
}
2070
2097
 
2071
2098
/*
2072
2099
  Create a table identical to the specified table
2073
2100
 
2074
2101
  SYNOPSIS
2075
 
    create_like_table()
 
2102
    mysql_create_like_table()
2076
2103
    session             Thread object
2077
2104
    table       Table list element for target table
2078
2105
    src_table   Table list element for source table
2083
2110
    true  error
2084
2111
*/
2085
2112
 
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)
 
2113
bool mysql_create_like_table(Session* session,
 
2114
                             TableIdentifier &destination_identifier,
 
2115
                             TableList* table, TableList* src_table,
 
2116
                             message::Table &create_table_proto,
 
2117
                             bool is_if_not_exists,
 
2118
                             bool is_engine_set)
2092
2119
{
 
2120
  Table *name_lock= 0;
 
2121
  char *db= table->db;
 
2122
  char *table_name= table->table_name;
2093
2123
  bool res= true;
2094
 
  bool table_exists= false;
 
2124
  uint32_t not_used;
 
2125
  bool was_created;
 
2126
 
 
2127
  /*
 
2128
    By opening source table we guarantee that it exists and no concurrent
 
2129
    DDL operation will mess with it. Later we also take an exclusive
 
2130
    name-lock on target table name, which makes copying of .frm cursor,
 
2131
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2132
    against concurrent DML and DDL operations on target table.
 
2133
    Thus by holding both these "locks" we ensure that our statement is
 
2134
    properly isolated from all concurrent operations which matter.
 
2135
  */
 
2136
  if (session->open_tables_from_list(&src_table, &not_used))
 
2137
    return true;
 
2138
 
 
2139
  TableIdentifier src_identifier(src_table->table->s->getSchemaName(),
 
2140
                                 src_table->table->s->table_name.str, src_table->table->s->tmp_table);
 
2141
 
 
2142
 
2095
2143
 
2096
2144
  /*
2097
2145
    Check that destination tables does not exist. Note that its name
2098
2146
    was already checked when it was added to the table list.
2099
 
 
2100
 
    For temporary tables we don't aim to grab locks.
2101
2147
  */
 
2148
  bool table_exists= false;
2102
2149
  if (destination_identifier.isTmp())
2103
2150
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
 
2151
    if (session->find_temporary_table(db, table_name))
2105
2152
    {
2106
2153
      table_exists= true;
2107
2154
    }
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
2155
  }
2130
 
  else // Standard table which will require locks.
 
2156
  else
2131
2157
  {
2132
 
    Table *name_lock= 0;
2133
 
 
2134
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
 
2158
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2135
2159
    {
2136
2160
      if (name_lock)
2137
2161
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2162
        pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2139
2163
        session->unlink_open_table(name_lock);
 
2164
        pthread_mutex_unlock(&LOCK_open);
2140
2165
      }
2141
2166
 
2142
2167
      return res;
2150
2175
    {
2151
2176
      table_exists= true;
2152
2177
    }
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
2178
  }
2180
2179
 
2181
2180
  if (table_exists)
2184
2183
    {
2185
2184
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
2185
      snprintf(warn_buff, sizeof(warn_buff),
2187
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2186
               ER(ER_TABLE_EXISTS_ERROR), table_name);
2188
2187
      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;
 
2188
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2189
      res= false;
 
2190
    }
 
2191
    else
 
2192
    {
 
2193
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2194
    }
 
2195
  }
 
2196
  else // Otherwise we create the table
 
2197
  {
 
2198
    pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2199
    was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2200
                                      src_identifier, is_engine_set);
 
2201
    pthread_mutex_unlock(&LOCK_open);
 
2202
 
 
2203
    // So we blew the creation of the table, and we scramble to clean up
 
2204
    // anything that might have been created (read... it is a hack)
 
2205
    if (not was_created)
 
2206
    {
 
2207
      if (destination_identifier.isTmp())
 
2208
      {
 
2209
        (void) session->rm_temporary_table(destination_identifier);
 
2210
      }
 
2211
      else
 
2212
      {
 
2213
        quick_rm_table(*session, destination_identifier);
 
2214
      }
 
2215
    } 
 
2216
    else if (destination_identifier.isTmp() && not session->open_temporary_table(destination_identifier))
 
2217
    {
 
2218
      // We created, but we can't open... also, a hack.
 
2219
      (void) session->rm_temporary_table(destination_identifier);
 
2220
    }
 
2221
    else
 
2222
    {
 
2223
      if (not destination_identifier.isTmp())
 
2224
      {
 
2225
        bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
 
2226
        (void)rc;
 
2227
      }
 
2228
 
 
2229
      res= false;
 
2230
    }
 
2231
  }
 
2232
 
 
2233
  if (name_lock)
 
2234
  {
 
2235
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2236
    session->unlink_open_table(name_lock);
 
2237
    pthread_mutex_unlock(&LOCK_open);
 
2238
  }
 
2239
 
 
2240
  return(res);
2199
2241
}
2200
2242
 
2201
2243
 
2202
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2244
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
2245
{
2204
2246
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
2247
 
2206
 
  return(admin_table(session, tables, check_opt,
 
2248
  return(mysql_admin_table(session, tables, check_opt,
2207
2249
                                "analyze", lock_type, true,
2208
2250
                                &Cursor::ha_analyze));
2209
2251
}
2210
2252
 
2211
2253
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2254
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
2255
{
2214
2256
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
2257
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2258
  return(mysql_admin_table(session, tables, check_opt,
2217
2259
                                "check", lock_type,
2218
2260
                                false,
2219
2261
                                &Cursor::ha_check));