~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2009-12-01 17:50:17 UTC
  • mto: (1235.1.1 push)
  • mto: This revision was merged to the branch mainline in revision 1236.
  • Revision ID: mordred@inaugust.com-20091201175017-o9yed6ssdiolghv4
Renamed instances of HEAP engine to MEMORY. Removed the alias.

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
 
18
 
#include "config.h"
 
18
#include <drizzled/server_includes.h>
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/data_home.h>
24
24
#include <drizzled/sql_parse.h>
25
 
#include <drizzled/my_hash.h>
 
25
#include <mysys/hash.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"
30
29
#include <drizzled/db.h>
31
30
#include <drizzled/lock.h>
32
31
#include <drizzled/unireg.h>
33
32
#include <drizzled/item/int.h>
34
33
#include <drizzled/item/empty_string.h>
35
 
#include <drizzled/transaction_services.h>
36
 
#include "drizzled/transaction_services.h"
 
34
#include <drizzled/replication_services.h>
37
35
#include <drizzled/table_proto.h>
38
36
#include <drizzled/plugin/client.h>
39
 
#include <drizzled/identifier.h>
40
 
#include "drizzled/internal/m_string.h"
41
 
#include "drizzled/global_charset_info.h"
42
 
#include "drizzled/charset.h"
43
 
 
44
 
#include "drizzled/definition/cache.h"
45
 
 
46
 
 
47
 
#include "drizzled/statement/alter_table.h"
48
 
#include "drizzled/sql_table.h"
49
 
#include "drizzled/pthread_globals.h"
 
37
#include <drizzled/table_identifier.h>
 
38
 
 
39
#include "drizzled/statement/alter_table.h" /* for drizzled::create_like_schema_frm, which will die soon */
50
40
 
51
41
#include <algorithm>
52
 
#include <sstream>
53
 
 
54
 
#include <boost/unordered_set.hpp>
55
42
 
56
43
using namespace std;
57
 
 
58
 
namespace drizzled
59
 
{
60
 
 
61
 
extern pid_t current_pid;
62
 
 
63
 
bool is_primary_key(KeyInfo *key_info)
 
44
using namespace drizzled;
 
45
 
 
46
static const char hexchars[]= "0123456789abcdef";
 
47
bool is_primary_key(KEY *key_info)
64
48
{
65
49
  static const char * primary_key_name="PRIMARY";
66
50
  return (strcmp(key_info->name, primary_key_name)==0);
75
59
    return NULL;
76
60
}
77
61
 
78
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
79
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
 
62
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
63
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
80
64
 
81
65
static bool prepare_blob_field(Session *session, CreateField *sql_field);
82
66
 
87
71
    let's fetch the database default character set and
88
72
    apply it to the table.
89
73
  */
90
 
  SchemaIdentifier identifier(db);
91
74
  if (create_info->default_table_charset == NULL)
92
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
75
    create_info->default_table_charset= get_default_db_collation(db);
 
76
}
 
77
 
 
78
/*
 
79
  Translate a cursor name to a table name (WL #1324).
 
80
 
 
81
  SYNOPSIS
 
82
    filename_to_tablename()
 
83
      from                      The cursor name
 
84
      to                OUT     The table name
 
85
      to_length                 The size of the table name buffer.
 
86
 
 
87
  RETURN
 
88
    Table name length.
 
89
*/
 
90
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
91
{
 
92
  uint32_t length= 0;
 
93
 
 
94
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
95
  {
 
96
    /* Temporary table name. */
 
97
    length= strlen(strncpy(to, from, to_length));
 
98
  }
 
99
  else
 
100
  {
 
101
    for (; *from  && length < to_length; length++, from++)
 
102
    {
 
103
      if (*from != '@')
 
104
      {
 
105
        to[length]= *from;
 
106
        continue;
 
107
      }
 
108
      /* We've found an escaped char - skip the @ */
 
109
      from++;
 
110
      to[length]= 0;
 
111
      /* There will be a two-position hex-char version of the char */
 
112
      for (int x=1; x >= 0; x--)
 
113
      {
 
114
        if (*from >= '0' && *from <= '9')
 
115
          to[length] += ((*from++ - '0') << (4 * x));
 
116
        else if (*from >= 'a' && *from <= 'f')
 
117
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
118
      }
 
119
      /* Backup because we advanced extra in the inner loop */
 
120
      from--;
 
121
    } 
 
122
  }
 
123
 
 
124
  return length;
 
125
}
 
126
 
 
127
 
 
128
/*
 
129
  Translate a table name to a cursor name (WL #1324).
 
130
 
 
131
  SYNOPSIS
 
132
    tablename_to_filename()
 
133
      from                      The table name
 
134
      to                OUT     The cursor name
 
135
      to_length                 The size of the cursor name buffer.
 
136
 
 
137
  RETURN
 
138
    true if errors happen. false on success.
 
139
*/
 
140
bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
141
{
 
142
  
 
143
  size_t length= 0;
 
144
  for (; *from  && length < to_length; length++, from++)
 
145
  {
 
146
    if ((*from >= '0' && *from <= '9') ||
 
147
        (*from >= 'A' && *from <= 'Z') ||
 
148
        (*from >= 'a' && *from <= 'z') ||
 
149
/* OSX defines an extra set of high-bit and multi-byte characters
 
150
   that cannot be used on the filesystem. Instead of trying to sort
 
151
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
152
   It won't really hurt anything - it'll just make some filenames ugly. */
 
153
#if !defined(TARGET_OS_OSX)
 
154
        ((unsigned char)*from >= 128) ||
 
155
#endif
 
156
        (*from == '_') ||
 
157
        (*from == ' ') ||
 
158
        (*from == '-'))
 
159
    {
 
160
      to[length]= *from;
 
161
      continue;
 
162
    }
 
163
   
 
164
    if (length + 3 >= to_length)
 
165
      return true;
 
166
 
 
167
    /* We need to escape this char in a way that can be reversed */
 
168
    to[length++]= '@';
 
169
    to[length++]= hexchars[(*from >> 4) & 15];
 
170
    to[length]= hexchars[(*from) & 15];
 
171
  }
 
172
 
 
173
  if (check_if_legal_tablename(to) &&
 
174
      length + 4 < to_length)
 
175
  {
 
176
    memcpy(to + length, "@@@", 4);
 
177
    length+= 3;
 
178
  }
 
179
  return false;
 
180
}
 
181
 
 
182
 
 
183
/*
 
184
  Creates path to a cursor: drizzle_data_dir/db/table.ext
 
185
 
 
186
  SYNOPSIS
 
187
   build_table_filename()
 
188
     buff                       Where to write result
 
189
                                This may be the same as table_name.
 
190
     bufflen                    buff size
 
191
     db                         Database name
 
192
     table_name                 Table name
 
193
     ext                        File extension.
 
194
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP
 
195
                                table_name is temporary, do not change.
 
196
 
 
197
  NOTES
 
198
 
 
199
    Uses database and table name, and extension to create
 
200
    a cursor name in drizzle_data_dir. Database and table
 
201
    names are converted from system_charset_info into "fscs".
 
202
    Unless flags indicate a temporary table name.
 
203
    'db' is always converted.
 
204
    'ext' is not converted.
 
205
 
 
206
    The conversion suppression is required for ALTER Table. This
 
207
    statement creates intermediate tables. These are regular
 
208
    (non-temporary) tables with a temporary name. Their path names must
 
209
    be derivable from the table name. So we cannot use
 
210
    build_tmptable_filename() for them.
 
211
 
 
212
  RETURN
 
213
    path length on success, 0 on failure
 
214
*/
 
215
 
 
216
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
 
217
{
 
218
  char dbbuff[FN_REFLEN];
 
219
  char tbbuff[FN_REFLEN];
 
220
  bool conversion_error= false;
 
221
 
 
222
  memset(tbbuff, 0, sizeof(tbbuff));
 
223
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
224
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
225
  else
 
226
  {
 
227
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
228
    if (conversion_error)
 
229
    {
 
230
      errmsg_printf(ERRMSG_LVL_ERROR,
 
231
                    _("Table name cannot be encoded and fit within filesystem "
 
232
                      "name length restrictions."));
 
233
      return 0;
 
234
    }
 
235
  }
 
236
  memset(dbbuff, 0, sizeof(dbbuff));
 
237
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
238
  if (conversion_error)
 
239
  {
 
240
    errmsg_printf(ERRMSG_LVL_ERROR,
 
241
                  _("Schema name cannot be encoded and fit within filesystem "
 
242
                    "name length restrictions."));
 
243
    return 0;
 
244
  }
 
245
   
 
246
 
 
247
  int rootdir_len= strlen(FN_ROOTDIR);
 
248
  string table_path(drizzle_data_home);
 
249
  int without_rootdir= table_path.length()-rootdir_len;
 
250
 
 
251
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
252
  if (without_rootdir >= 0)
 
253
  {
 
254
    const char *tmp= table_path.c_str()+without_rootdir;
 
255
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
256
      table_path.append(FN_ROOTDIR);
 
257
  }
 
258
 
 
259
  table_path.append(dbbuff);
 
260
  table_path.append(FN_ROOTDIR);
 
261
  table_path.append(tbbuff);
 
262
 
 
263
  if (bufflen < table_path.length())
 
264
    return 0;
 
265
 
 
266
  strcpy(buff, table_path.c_str());
 
267
 
 
268
  return table_path.length();
 
269
}
 
270
 
 
271
 
 
272
/*
 
273
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
 
274
 
 
275
  SYNOPSIS
 
276
   build_tmptable_filename()
 
277
     session                    The thread handle.
 
278
     buff                       Where to write result
 
279
     bufflen                    buff size
 
280
 
 
281
  NOTES
 
282
 
 
283
    Uses current_pid, thread_id, and tmp_table counter to create
 
284
    a cursor name in drizzle_tmpdir.
 
285
 
 
286
  RETURN
 
287
    path length on success, 0 on failure
 
288
*/
 
289
 
 
290
size_t build_tmptable_filename(char *buff, size_t bufflen)
 
291
{
 
292
  size_t length;
 
293
  ostringstream path_str, post_tmpdir_str;
 
294
  string tmp;
 
295
 
 
296
  Session *session= current_session;
 
297
 
 
298
  path_str << drizzle_tmpdir;
 
299
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
300
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
301
  tmp= post_tmpdir_str.str();
 
302
 
 
303
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
304
 
 
305
  path_str << tmp;
 
306
 
 
307
  if (bufflen < path_str.str().length())
 
308
    length= 0;
 
309
  else
 
310
    length= unpack_filename(buff, path_str.str().c_str());
 
311
 
 
312
  return length;
93
313
}
94
314
 
95
315
/*
107
327
    cursor
108
328
*/
109
329
 
110
 
void write_bin_log(Session *session, const std::string &query)
111
 
{
112
 
  TransactionServices &transaction_services= TransactionServices::singleton();
113
 
  transaction_services.rawStatement(session, query);
 
330
void write_bin_log(Session *session,
 
331
                   char const *query, size_t query_length)
 
332
{
 
333
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
334
  replication_services.rawStatement(session, query, query_length);
 
335
}
 
336
 
 
337
 
 
338
/* Should should be refactored to go away */
 
339
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
340
{
 
341
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
342
  string built_query;
 
343
 
 
344
  if (if_exists)
 
345
    built_query.append("DROP TABLE IF EXISTS ");
 
346
  else
 
347
    built_query.append("DROP TABLE ");
 
348
 
 
349
  built_query.append("`");
 
350
  if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
 
351
  {
 
352
    built_query.append(db_name);
 
353
    built_query.append("`.`");
 
354
  }
 
355
 
 
356
  built_query.append(table_name);
 
357
  built_query.append("`");
 
358
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
114
359
}
115
360
 
116
361
/*
124
369
                        In this case we give an warning of level 'NOTE'
125
370
    drop_temporary      Only drop temporary tables
126
371
 
127
 
  @todo
 
372
  TODO:
128
373
    When logging to the binary log, we should log
129
374
    tmp_tables and transactional tables as separate statements if we
130
375
    are in a transaction;  This is needed to get these tables into the
144
389
                         bool drop_temporary)
145
390
{
146
391
  TableList *table;
 
392
  char path[FN_REFLEN];
 
393
  uint32_t path_length= 0;
147
394
  String wrong_tables;
148
395
  int error= 0;
149
396
  bool foreign_key_error= false;
150
397
 
151
 
  {
152
 
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
153
 
 
154
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
 
    {
156
 
      table::Cache::singleton().mutex().unlock();
157
 
      return 1;
158
 
    }
159
 
 
160
 
    /* Don't give warnings for not found errors, as we already generate notes */
161
 
    session->no_warnings_for_error= 1;
162
 
 
163
 
    for (table= tables; table; table= table->next_local)
164
 
    {
165
 
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
166
 
 
167
 
      error= session->drop_temporary_table(tmp_identifier);
168
 
 
169
 
      switch (error) {
170
 
      case  0:
171
 
        // removed temporary table
172
 
        continue;
173
 
      case -1:
 
398
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
399
 
 
400
  /*
 
401
    If we have the table in the definition cache, we don't have to check the
 
402
    .frm cursor to find if the table is a normal table (not view) and what
 
403
    engine to use.
 
404
  */
 
405
 
 
406
  for (table= tables; table; table= table->next_local)
 
407
  {
 
408
    TableShare *share;
 
409
    table->db_type= NULL;
 
410
    if ((share= TableShare::getShare(table->db, table->table_name)))
 
411
      table->db_type= share->db_type();
 
412
  }
 
413
 
 
414
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
415
  {
 
416
    pthread_mutex_unlock(&LOCK_open);
 
417
    return 1;
 
418
  }
 
419
 
 
420
  /* Don't give warnings for not found errors, as we already generate notes */
 
421
  session->no_warnings_for_error= 1;
 
422
 
 
423
  for (table= tables; table; table= table->next_local)
 
424
  {
 
425
    char *db=table->db;
 
426
    plugin::StorageEngine *table_type;
 
427
 
 
428
    error= session->drop_temporary_table(table);
 
429
 
 
430
    switch (error) {
 
431
    case  0:
 
432
      // removed temporary table
 
433
      continue;
 
434
    case -1:
 
435
      error= 1;
 
436
      goto err_with_placeholders;
 
437
    default:
 
438
      // temporary table not found
 
439
      error= 0;
 
440
    }
 
441
 
 
442
    table_type= table->db_type;
 
443
    if (drop_temporary == false)
 
444
    {
 
445
      Table *locked_table;
 
446
      abort_locked_tables(session, db, table->table_name);
 
447
      remove_table_from_cache(session, db, table->table_name,
 
448
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
449
                              RTFC_CHECK_KILLED_FLAG);
 
450
      /*
 
451
        If the table was used in lock tables, remember it so that
 
452
        unlock_table_names can free it
 
453
      */
 
454
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
455
        table->table= locked_table;
 
456
 
 
457
      if (session->killed)
 
458
      {
 
459
        error= -1;
 
460
        goto err_with_placeholders;
 
461
      }
 
462
      /* remove .frm cursor and engine files */
 
463
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
 
464
    }
 
465
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
 
466
 
 
467
    if (drop_temporary ||
 
468
        ((table_type == NULL
 
469
          && (plugin::StorageEngine::getTableDefinition(*session,
 
470
                                                        identifier) != EEXIST))))
 
471
    {
 
472
      // Table was not found on disk and table can't be created from engine
 
473
      if (if_exists)
 
474
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
475
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
476
                            table->table_name);
 
477
      else
174
478
        error= 1;
175
 
        goto err_with_placeholders;
176
 
      default:
177
 
        // temporary table not found
178
 
        error= 0;
179
 
      }
180
 
 
181
 
      if (drop_temporary == false)
182
 
      {
183
 
        Table *locked_table;
184
 
        abort_locked_tables(session, tmp_identifier);
185
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
186
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
187
 
                                              RTFC_CHECK_KILLED_FLAG);
188
 
        /*
189
 
          If the table was used in lock tables, remember it so that
190
 
          unlock_table_names can free it
191
 
        */
192
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
193
 
          table->table= locked_table;
194
 
 
195
 
        if (session->getKilled())
196
 
        {
197
 
          error= -1;
198
 
          goto err_with_placeholders;
199
 
        }
200
 
      }
201
 
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
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
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
208
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
209
 
                              table->getTableName());
210
 
        else
211
 
          error= 1;
212
 
      }
213
 
      else
214
 
      {
215
 
        error= plugin::StorageEngine::dropTable(*session, identifier);
216
 
 
217
 
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
218
 
        {
219
 
          error= 0;
220
 
          session->clear_error();
221
 
        }
222
 
 
223
 
        if (error == HA_ERR_ROW_IS_REFERENCED)
224
 
        {
225
 
          /* the table is referenced by a foreign key constraint */
226
 
          foreign_key_error= true;
227
 
        }
228
 
      }
229
 
 
230
 
      if (error == 0 || (if_exists && foreign_key_error == false))
231
 
      {
232
 
        TransactionServices &transaction_services= TransactionServices::singleton();
233
 
        transaction_services.dropTable(session, string(table->getSchemaName()), string(table->getTableName()), if_exists);
234
 
      }
235
 
 
236
 
      if (error)
237
 
      {
238
 
        if (wrong_tables.length())
239
 
          wrong_tables.append(',');
240
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
241
 
      }
242
 
    }
243
 
    /*
244
 
      It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
245
 
      on the table name.
246
 
    */
247
 
    table::Cache::singleton().mutex().unlock();
 
479
    }
 
480
    else
 
481
    {
 
482
      error= plugin::StorageEngine::dropTable(*session,
 
483
                                              identifier,
 
484
                                              true);
 
485
 
 
486
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
487
      {
 
488
        error= 0;
 
489
        session->clear_error();
 
490
      }
 
491
 
 
492
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
493
      {
 
494
        /* the table is referenced by a foreign key constraint */
 
495
        foreign_key_error= true;
 
496
      }
 
497
    }
 
498
 
 
499
    if (error == 0 || (if_exists && foreign_key_error == false))
 
500
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
501
 
 
502
    if (error)
 
503
    {
 
504
      if (wrong_tables.length())
 
505
        wrong_tables.append(',');
 
506
      wrong_tables.append(String(table->table_name,system_charset_info));
 
507
    }
248
508
  }
 
509
  /*
 
510
    It's safe to unlock LOCK_open: we have an exclusive lock
 
511
    on the table name.
 
512
  */
 
513
  pthread_mutex_unlock(&LOCK_open);
249
514
  error= 0;
250
 
 
251
515
  if (wrong_tables.length())
252
516
  {
253
 
    if (not foreign_key_error)
254
 
    {
 
517
    if (!foreign_key_error)
255
518
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
519
                      wrong_tables.c_ptr());
257
 
    }
258
520
    else
259
521
    {
260
522
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
262
524
    error= 1;
263
525
  }
264
526
 
265
 
  table::Cache::singleton().mutex().lock(); /* final bit in rm table lock */
266
 
 
 
527
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
267
528
err_with_placeholders:
268
 
  tables->unlock_table_names();
269
 
  table::Cache::singleton().mutex().unlock();
 
529
  unlock_table_names(tables, NULL);
 
530
  pthread_mutex_unlock(&LOCK_open);
270
531
  session->no_warnings_for_error= 0;
271
532
 
272
 
  return error;
 
533
  return(error);
 
534
}
 
535
 
 
536
 
 
537
/*
 
538
  Quickly remove a table.
 
539
 
 
540
  SYNOPSIS
 
541
    quick_rm_table()
 
542
      base                      The plugin::StorageEngine handle.
 
543
      db                        The database name.
 
544
      table_name                The table name.
 
545
      is_tmp                    If the table is temp.
 
546
 
 
547
  RETURN
 
548
    0           OK
 
549
    != 0        Error
 
550
*/
 
551
 
 
552
bool quick_rm_table(Session& session, const char *db,
 
553
                    const char *table_name, bool is_tmp)
 
554
{
 
555
  bool error= 0;
 
556
 
 
557
  TableIdentifier identifier(db, table_name, is_tmp ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
 
558
 
 
559
  return (plugin::StorageEngine::dropTable(session, identifier, false)
 
560
          || error);
273
561
}
274
562
 
275
563
/*
285
573
  PRIMARY keys are prioritized.
286
574
*/
287
575
 
288
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
576
static int sort_keys(KEY *a, KEY *b)
289
577
{
290
578
  ulong a_flags= a->flags, b_flags= b->flags;
291
579
 
337
625
    1             Error
338
626
*/
339
627
 
340
 
class typelib_set_member
341
 
{
342
 
public:
343
 
  string s;
344
 
  const CHARSET_INFO * const cs;
345
 
 
346
 
  typelib_set_member(const char* value, unsigned int length,
347
 
                     const CHARSET_INFO * const charset)
348
 
    : s(value, length),
349
 
      cs(charset)
350
 
  {}
351
 
};
352
 
 
353
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
354
 
{
355
 
  return (my_strnncoll(a.cs,
356
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
357
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
358
 
}
359
 
 
360
 
 
361
 
namespace
362
 
{
363
 
class typelib_set_member_hasher
364
 
{
365
 
  boost::hash<string> hasher;
366
 
public:
367
 
  std::size_t operator()(const typelib_set_member& t) const
368
 
  {
369
 
    return hasher(t.s);
370
 
  }
371
 
};
372
 
}
373
 
 
374
628
static bool check_duplicates_in_interval(const char *set_or_name,
375
629
                                         const char *name, TYPELIB *typelib,
376
630
                                         const CHARSET_INFO * const cs,
381
635
  unsigned int *cur_length= typelib->type_lengths;
382
636
  *dup_val_count= 0;
383
637
 
384
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
385
 
 
386
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
638
  for ( ; tmp.count > 1; cur_value++, cur_length++)
387
639
  {
388
640
    tmp.type_names++;
389
641
    tmp.type_lengths++;
390
642
    tmp.count--;
391
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
643
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
392
644
    {
393
645
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
394
646
               name,*cur_value,set_or_name);
395
647
      return 1;
396
648
    }
397
 
    else
398
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
399
649
  }
400
650
  return 0;
401
651
}
444
694
    sql_field     field to prepare for packing
445
695
    blob_columns  count for BLOBs
446
696
    timestamps    count for timestamps
 
697
    table_flags   table flags
447
698
 
448
699
  DESCRIPTION
449
700
    This function prepares a CreateField instance.
455
706
*/
456
707
int prepare_create_field(CreateField *sql_field,
457
708
                         uint32_t *blob_columns,
458
 
                         int *timestamps,
459
 
                         int *timestamps_with_niladic)
 
709
                         int *timestamps, int *timestamps_with_niladic,
 
710
                         int64_t )
460
711
{
461
712
  unsigned int dup_val_count;
462
713
 
468
719
 
469
720
  switch (sql_field->sql_type) {
470
721
  case DRIZZLE_TYPE_BLOB:
 
722
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
471
723
    sql_field->length= 8; // Unireg field length
472
724
    (*blob_columns)++;
473
725
    break;
474
726
  case DRIZZLE_TYPE_VARCHAR:
 
727
    sql_field->pack_flag=0;
475
728
    break;
476
729
  case DRIZZLE_TYPE_ENUM:
 
730
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
477
731
    if (check_duplicates_in_interval("ENUM",
478
732
                                     sql_field->field_name,
479
733
                                     sql_field->interval,
484
738
  case DRIZZLE_TYPE_DATE:  // Rest of string types
485
739
  case DRIZZLE_TYPE_DATETIME:
486
740
  case DRIZZLE_TYPE_NULL:
 
741
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
487
742
    break;
488
743
  case DRIZZLE_TYPE_DECIMAL:
 
744
    sql_field->pack_flag= 0;
489
745
    break;
490
746
  case DRIZZLE_TYPE_TIMESTAMP:
491
747
    /* We should replace old TIMESTAMP fields with their newer analogs */
497
753
        (*timestamps_with_niladic)++;
498
754
      }
499
755
      else
500
 
      {
501
756
        sql_field->unireg_check= Field::NONE;
502
 
      }
503
757
    }
504
758
    else if (sql_field->unireg_check != Field::NONE)
505
759
      (*timestamps_with_niladic)++;
507
761
    (*timestamps)++;
508
762
    /* fall-through */
509
763
  default:
 
764
    sql_field->pack_flag=(0 |
 
765
                          f_settype((uint32_t) sql_field->sql_type));
510
766
    break;
511
767
  }
512
 
 
513
768
  return 0;
514
769
}
515
770
 
516
 
static int mysql_prepare_create_table(Session *session,
517
 
                                      HA_CREATE_INFO *create_info,
518
 
                                      message::Table &create_proto,
519
 
                                      AlterInfo *alter_info,
520
 
                                      bool tmp_table,
521
 
                                      uint32_t *db_options,
522
 
                                      KeyInfo **key_info_buffer,
523
 
                                      uint32_t *key_count,
524
 
                                      int select_field_count)
 
771
int mysql_prepare_create_table(Session *session,
 
772
                               HA_CREATE_INFO *create_info,
 
773
                               message::Table *create_proto,
 
774
                               AlterInfo *alter_info,
 
775
                               bool tmp_table,
 
776
                               uint32_t *db_options,
 
777
                               Cursor *cursor,
 
778
                               KEY **key_info_buffer,
 
779
                               uint32_t *key_count,
 
780
                               int select_field_count)
525
781
{
526
782
  const char    *key_name;
527
783
  CreateField   *sql_field,*dup_field;
528
784
  uint          field,null_fields,blob_columns,max_key_length;
529
785
  ulong         record_offset= 0;
530
 
  KeyInfo               *key_info;
531
 
  KeyPartInfo *key_part_info;
 
786
  KEY           *key_info;
 
787
  KEY_PART_INFO *key_part_info;
532
788
  int           timestamps= 0, timestamps_with_niladic= 0;
533
789
  int           field_no,dup_no;
534
790
  int           select_field_pos,auto_increment=0;
536
792
  List_iterator<CreateField> it2(alter_info->create_list);
537
793
  uint32_t total_uneven_bit_length= 0;
538
794
 
539
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
540
 
 
541
795
  select_field_pos= alter_info->create_list.elements - select_field_count;
542
796
  null_fields=blob_columns=0;
543
 
  max_key_length= engine->max_key_length();
 
797
  max_key_length= cursor->max_key_length();
544
798
 
545
799
  for (field_no=0; (sql_field=it++) ; field_no++)
546
800
  {
606
860
 
607
861
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
608
862
    {
609
 
      size_t dummy;
 
863
      uint32_t dummy;
610
864
      const CHARSET_INFO * const cs= sql_field->charset;
611
865
      TYPELIB *interval= sql_field->interval;
612
866
 
639
893
          if (String::needs_conversion(tmp->length(), tmp->charset(),
640
894
                                       cs, &dummy))
641
895
          {
642
 
            size_t cnv_errs;
 
896
            uint32_t cnv_errs;
643
897
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
644
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
898
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
899
                                                  conv.length());
645
900
            interval->type_lengths[i]= conv.length();
646
901
          }
647
902
 
681
936
            }
682
937
          }
683
938
        }
684
 
        uint32_t new_dummy;
685
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
939
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
686
940
        sql_field->length= field_length;
687
941
      }
688
942
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
746
1000
        }
747
1001
      }
748
1002
    }
749
 
 
750
 
    /** @todo Get rid of this MyISAM-specific crap. */
751
 
    if (not create_proto.engine().name().compare("MyISAM") &&
752
 
        ((sql_field->flags & BLOB_FLAG) ||
753
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
 
1003
    /* Don't pack rows in old tables if the user has requested this */
 
1004
    if ((sql_field->flags & BLOB_FLAG) ||
 
1005
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
754
1006
      (*db_options)|= HA_OPTION_PACK_RECORD;
755
1007
    it2.rewind();
756
1008
  }
765
1017
    assert(sql_field->charset != 0);
766
1018
 
767
1019
    if (prepare_create_field(sql_field, &blob_columns,
768
 
                             &timestamps, &timestamps_with_niladic))
 
1020
                             &timestamps, &timestamps_with_niladic,
 
1021
                             cursor->ha_table_flags()))
769
1022
      return(true);
770
1023
    sql_field->offset= record_offset;
771
1024
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
783
1036
    return(true);
784
1037
  }
785
1038
  if (auto_increment &&
786
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1039
      (cursor->ha_table_flags() & HA_NO_AUTO_INCREMENT))
787
1040
  {
788
1041
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
789
1042
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
790
1043
    return(true);
791
1044
  }
792
1045
 
793
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1046
  if (blob_columns && (cursor->ha_table_flags() & HA_NO_BLOBS))
794
1047
  {
795
1048
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
796
1049
               MYF(0));
818
1071
      fk_key_count++;
819
1072
      if (((Foreign_key *)key)->validate(alter_info->create_list))
820
1073
        return true;
821
 
 
822
1074
      Foreign_key *fk_key= (Foreign_key*) key;
823
 
 
824
 
      add_foreign_key_to_table_message(&create_proto,
825
 
                                       fk_key->name.str,
826
 
                                       fk_key->columns,
827
 
                                       fk_key->ref_table,
828
 
                                       fk_key->ref_columns,
829
 
                                       fk_key->delete_opt,
830
 
                                       fk_key->update_opt,
831
 
                                       fk_key->match_opt);
832
 
 
833
1075
      if (fk_key->ref_columns.elements &&
834
1076
          fk_key->ref_columns.elements != fk_key->columns.elements)
835
1077
      {
842
1084
      continue;
843
1085
    }
844
1086
    (*key_count)++;
845
 
    tmp= engine->max_key_parts();
 
1087
    tmp=cursor->max_key_parts();
846
1088
    if (key->columns.elements > tmp)
847
1089
    {
848
1090
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
864
1106
             key2->name.str != ignore_key &&
865
1107
             !foreign_key_prefix(key, key2)))
866
1108
        {
867
 
          /* @todo issue warning message */
 
1109
          /* TODO: issue warning message */
868
1110
          /* mark that the generated key should be ignored */
869
1111
          if (!key2->generated ||
870
1112
              (key->generated && key->columns.elements <
891
1133
      return(true);
892
1134
    }
893
1135
  }
894
 
  tmp= engine->max_keys();
 
1136
  tmp=cursor->max_keys();
895
1137
  if (*key_count > tmp)
896
1138
  {
897
1139
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
898
1140
    return(true);
899
1141
  }
900
1142
 
901
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
902
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
1143
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1144
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
903
1145
  if (!*key_info_buffer || ! key_part_info)
904
1146
    return(true);                               // Out of memory
905
1147
 
939
1181
    key_info->usable_key_parts= key_number;
940
1182
    key_info->algorithm= key->key_create_info.algorithm;
941
1183
 
 
1184
    /* Take block size from key part or table part */
 
1185
    /*
 
1186
      TODO: Add warning if block size changes. We can't do it here, as
 
1187
      this may depend on the size of the key
 
1188
    */
 
1189
    key_info->block_size= (key->key_create_info.block_size ?
 
1190
                           key->key_create_info.block_size :
 
1191
                           create_proto->options().key_block_size());
 
1192
 
 
1193
    if (key_info->block_size)
 
1194
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
1195
 
942
1196
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
943
1197
                                           key->key_create_info.comment.str,
944
1198
                                           key->key_create_info.comment.str +
984
1238
      while ((dup_column= cols2++) != column)
985
1239
      {
986
1240
        if (!my_strcasecmp(system_charset_info,
987
 
                           column->field_name.str, dup_column->field_name.str))
 
1241
                           column->field_name.str, dup_column->field_name.str))
988
1242
        {
989
1243
          my_printf_error(ER_DUP_FIELDNAME,
990
1244
                          ER(ER_DUP_FIELDNAME),MYF(0),
994
1248
      }
995
1249
      cols2.rewind();
996
1250
 
997
 
      if (create_proto.field_size() > 0)
998
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
 
1251
      if (create_proto->field_size() > 0)
 
1252
        protofield= create_proto->mutable_field(proto_field_nr - 1);
999
1253
 
1000
1254
      {
1001
1255
        column->length*= sql_field->charset->mbmaxlen;
1002
1256
 
1003
1257
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1004
1258
        {
1005
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
 
1259
          if (! (cursor->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1006
1260
          {
1007
1261
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1008
1262
            return true;
1032
1286
          else
1033
1287
          {
1034
1288
            key_info->flags|= HA_NULL_PART_KEY;
1035
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1289
            if (! (cursor->ha_table_flags() & HA_NULL_IN_KEY))
1036
1290
            {
1037
1291
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1038
1292
              return true;
1041
1295
        }
1042
1296
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1043
1297
        {
1044
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
 
1298
          if (column_nr == 0 || (cursor->ha_table_flags() & HA_AUTO_PART_KEY))
1045
1299
            auto_increment--;                   // Field is used
1046
1300
        }
1047
1301
      }
1048
1302
 
1049
1303
      key_part_info->fieldnr= field;
1050
1304
      key_part_info->offset=  (uint16_t) sql_field->offset;
1051
 
      key_part_info->key_type= 0;
 
1305
      key_part_info->key_type=sql_field->pack_flag;
1052
1306
      length= sql_field->key_length;
1053
1307
 
1054
1308
      if (column->length)
1056
1310
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1057
1311
        {
1058
1312
          if ((length=column->length) > max_key_length ||
1059
 
              length > engine->max_key_part_length())
 
1313
              length > cursor->max_key_part_length())
1060
1314
          {
1061
 
            length= min(max_key_length, engine->max_key_part_length());
 
1315
            length= min(max_key_length, cursor->max_key_part_length());
1062
1316
            if (key->type == Key::MULTIPLE)
1063
1317
            {
1064
1318
              /* not a critical problem */
1083
1337
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1084
1338
          return(true);
1085
1339
        }
1086
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1087
 
        {
 
1340
        else if (!(cursor->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1088
1341
          length=column->length;
1089
 
        }
1090
1342
      }
1091
1343
      else if (length == 0)
1092
1344
      {
1093
1345
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1094
1346
          return(true);
1095
1347
      }
1096
 
      if (length > engine->max_key_part_length())
 
1348
      if (length > cursor->max_key_part_length())
1097
1349
      {
1098
 
        length= engine->max_key_part_length();
 
1350
        length= cursor->max_key_part_length();
1099
1351
        if (key->type == Key::MULTIPLE)
1100
1352
        {
1101
1353
          /* not a critical problem */
1116
1368
      key_part_info->length=(uint16_t) length;
1117
1369
      /* Use packed keys for long strings on the first column */
1118
1370
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1119
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1120
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1121
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1371
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1372
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1373
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1122
1374
      {
1123
1375
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1124
1376
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1125
 
        {
1126
1377
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1127
 
        }
1128
1378
        else
1129
 
        {
1130
1379
          key_info->flags|= HA_PACK_KEY;
1131
 
        }
1132
1380
      }
1133
1381
      /* Check if the key segment is partial, set the key flag accordingly */
1134
1382
      if (length != sql_field->key_length)
1179
1427
    key_info++;
1180
1428
  }
1181
1429
  if (!unique_key && !primary_key &&
1182
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1430
      (cursor->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1183
1431
  {
1184
1432
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1185
1433
    return(true);
1190
1438
    return(true);
1191
1439
  }
1192
1440
  /* Sort keys in optimized order */
1193
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1194
 
                     (qsort_cmp) sort_keys);
 
1441
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1442
           (qsort_cmp) sort_keys);
1195
1443
 
1196
1444
  /* Check fields. */
1197
1445
  it.rewind();
1264
1512
  return 0;
1265
1513
}
1266
1514
 
1267
 
static bool locked_create_event(Session *session,
1268
 
                                const TableIdentifier &identifier,
1269
 
                                HA_CREATE_INFO *create_info,
1270
 
                                message::Table &table_proto,
1271
 
                                AlterInfo *alter_info,
1272
 
                                bool is_if_not_exists,
1273
 
                                bool internal_tmp_table,
1274
 
                                uint db_options,
1275
 
                                uint key_count,
1276
 
                                KeyInfo *key_info_buffer)
1277
 
{
1278
 
  bool error= true;
1279
 
 
1280
 
  {
1281
 
 
1282
 
    /*
1283
 
      @note if we are building a temp table we need to check to see if a temp table
1284
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1285
 
      to create a table under a temporary table.
1286
 
    */
1287
 
    bool exists= 
1288
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1289
 
                                            identifier.getType() != message::Table::STANDARD );
1290
 
 
1291
 
    if (exists)
1292
 
    {
1293
 
      if (is_if_not_exists)
1294
 
      {
1295
 
        error= false;
1296
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1297
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1298
 
                            identifier.getTableName().c_str());
1299
 
        create_info->table_existed= 1;          // Mark that table existed
1300
 
        return error;
1301
 
      }
1302
 
 
1303
 
      std::string path;
1304
 
      identifier.getSQLPath(path);
1305
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1306
 
 
1307
 
      return error;
1308
 
    }
1309
 
 
1310
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1311
 
    {
1312
 
      /*
1313
 
        We don't assert here, but check the result, because the table could be
1314
 
        in the table definition cache and in the same time the .frm could be
1315
 
        missing from the disk, in case of manual intervention which deletes
1316
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1317
 
        Then she could create the table. This case is pretty obscure and
1318
 
        therefore we don't introduce a new error message only for it.
1319
 
      */
1320
 
      /*
1321
 
        @todo improve this error condition.
1322
 
      */
1323
 
      if (definition::Cache::singleton().find(identifier.getKey()))
1324
 
      {
1325
 
        std::string path;
1326
 
        identifier.getSQLPath(path);
1327
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1328
 
 
1329
 
        return error;
1330
 
      }
1331
 
    }
1332
 
  }
1333
 
 
1334
 
  session->set_proc_info("creating table");
1335
 
  create_info->table_existed= 0;                // Mark that table is created
1336
 
 
1337
 
  create_info->table_options= db_options;
1338
 
 
1339
 
  if (not rea_create_table(session, identifier,
1340
 
                           table_proto,
1341
 
                           create_info, alter_info->create_list,
1342
 
                           key_count, key_info_buffer))
1343
 
  {
1344
 
    return error;
1345
 
  }
1346
 
 
1347
 
  if (identifier.getType() == message::Table::TEMPORARY)
1348
 
  {
1349
 
    /* Open table and put in temporary table list */
1350
 
    if (not (session->open_temporary_table(identifier)))
1351
 
    {
1352
 
      (void) session->rm_temporary_table(identifier);
1353
 
      return error;
1354
 
    }
1355
 
  }
1356
 
 
1357
 
  /* 
1358
 
    We keep this behind the lock to make sure ordering is correct for a table.
1359
 
    This is a very unlikely problem where before we would write out to the
1360
 
    trans log, someone would do a delete/create operation.
1361
 
  */
1362
 
 
1363
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1364
 
  {
1365
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1366
 
    transaction_services.createTable(session, table_proto);
1367
 
  }
1368
 
 
1369
 
  return false;
1370
 
}
1371
 
 
1372
1515
 
1373
1516
/*
1374
1517
  Ignore the name of this function... it locks :(
1401
1544
*/
1402
1545
 
1403
1546
bool mysql_create_table_no_lock(Session *session,
1404
 
                                const TableIdentifier &identifier,
 
1547
                                TableIdentifier &identifier,
1405
1548
                                HA_CREATE_INFO *create_info,
1406
 
                                message::Table &table_proto,
 
1549
                                message::Table *table_proto,
1407
1550
                                AlterInfo *alter_info,
1408
1551
                                bool internal_tmp_table,
1409
 
                                uint32_t select_field_count,
 
1552
                                uint32_t select_field_count, 
1410
1553
                                bool is_if_not_exists)
1411
1554
{
1412
1555
  uint          db_options, key_count;
1413
 
  KeyInfo               *key_info_buffer;
 
1556
  KEY           *key_info_buffer;
 
1557
  Cursor        *cursor;
1414
1558
  bool          error= true;
 
1559
  TableShare share;
 
1560
  bool lex_identified_temp_table= 
 
1561
    (table_proto->type() == drizzled::message::Table::TEMPORARY);
1415
1562
 
1416
1563
  /* Check for duplicate fields and check type of table to create */
1417
 
  if (not alter_info->create_list.elements)
 
1564
  if (!alter_info->create_list.elements)
1418
1565
  {
1419
1566
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1420
1567
               MYF(0));
1421
1568
    return true;
1422
1569
  }
1423
 
  assert(identifier.getTableName() == table_proto.name());
 
1570
  assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
1424
1571
  db_options= create_info->table_options;
1425
 
 
1426
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1427
 
 
1428
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1429
 
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1430
 
                                     internal_tmp_table,
1431
 
                                     &db_options,
1432
 
                                     &key_info_buffer, &key_count,
1433
 
                                     select_field_count))
1434
 
  {
1435
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1436
 
    error= locked_create_event(session,
1437
 
                               identifier,
1438
 
                               create_info,
1439
 
                               table_proto,
1440
 
                               alter_info,
1441
 
                               is_if_not_exists,
1442
 
                               internal_tmp_table,
1443
 
                               db_options, key_count,
1444
 
                               key_info_buffer);
1445
 
  }
1446
 
 
1447
 
  session->set_proc_info("After create");
1448
 
 
1449
 
  return(error);
1450
 
}
1451
 
 
1452
 
/**
1453
 
  @note the following two methods implement create [temporary] table.
1454
 
*/
1455
 
static bool drizzle_create_table(Session *session,
1456
 
                                 const TableIdentifier &identifier,
1457
 
                                 HA_CREATE_INFO *create_info,
1458
 
                                 message::Table &table_proto,
1459
 
                                 AlterInfo *alter_info,
1460
 
                                 bool internal_tmp_table,
1461
 
                                 uint32_t select_field_count,
1462
 
                                 bool is_if_not_exists)
1463
 
{
1464
 
  Table *name_lock= NULL;
1465
 
  bool result;
1466
 
 
1467
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1468
 
  {
1469
 
    result= true;
1470
 
  }
1471
 
  else if (name_lock == NULL)
 
1572
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1573
    db_options|=HA_OPTION_PACK_RECORD;
 
1574
  if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
 
1575
  {
 
1576
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
 
1577
    return true;
 
1578
  }
 
1579
 
 
1580
  set_table_default_charset(create_info, identifier.getDBName());
 
1581
 
 
1582
  /* Check if table exists */
 
1583
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1584
                                 internal_tmp_table,
 
1585
                                 &db_options, cursor,
 
1586
                                 &key_info_buffer, &key_count,
 
1587
                                 select_field_count))
 
1588
    goto err;
 
1589
 
 
1590
  /* Check if table already exists */
 
1591
  if (lex_identified_temp_table &&
 
1592
      session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1472
1593
  {
1473
1594
    if (is_if_not_exists)
1474
1595
    {
 
1596
      create_info->table_existed= 1;            // Mark that table existed
1475
1597
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1476
1598
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1477
 
                          identifier.getTableName().c_str());
1478
 
      create_info->table_existed= 1;
1479
 
      result= false;
1480
 
    }
1481
 
    else
1482
 
    {
1483
 
      std::string path;
1484
 
      identifier.getSQLPath(path);
1485
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1486
 
      result= true;
1487
 
    }
1488
 
  }
1489
 
  else
1490
 
  {
1491
 
    result= mysql_create_table_no_lock(session,
1492
 
                                       identifier,
1493
 
                                       create_info,
1494
 
                                       table_proto,
1495
 
                                       alter_info,
1496
 
                                       internal_tmp_table,
1497
 
                                       select_field_count,
1498
 
                                       is_if_not_exists);
1499
 
  }
1500
 
 
1501
 
  if (name_lock)
1502
 
  {
1503
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1504
 
    session->unlink_open_table(name_lock);
1505
 
  }
1506
 
 
1507
 
  return(result);
 
1599
                          identifier.getTableName());
 
1600
      error= 0;
 
1601
      goto err;
 
1602
    }
 
1603
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1604
    goto err;
 
1605
  }
 
1606
 
 
1607
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1608
  if (!internal_tmp_table && ! lex_identified_temp_table)
 
1609
  {
 
1610
    if (plugin::StorageEngine::getTableDefinition(*session,
 
1611
                                                  identifier)==EEXIST)
 
1612
    {
 
1613
      if (is_if_not_exists)
 
1614
      {
 
1615
        error= false;
 
1616
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1617
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1618
                            identifier.getTableName());
 
1619
        create_info->table_existed= 1;          // Mark that table existed
 
1620
      }
 
1621
      else 
 
1622
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1623
 
 
1624
      goto unlock_and_end;
 
1625
    }
 
1626
    /*
 
1627
      We don't assert here, but check the result, because the table could be
 
1628
      in the table definition cache and in the same time the .frm could be
 
1629
      missing from the disk, in case of manual intervention which deletes
 
1630
      the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
 
1631
      Then she could create the table. This case is pretty obscure and
 
1632
      therefore we don't introduce a new error message only for it.
 
1633
    */
 
1634
    if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
 
1635
    {
 
1636
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1637
      goto unlock_and_end;
 
1638
    }
 
1639
  }
 
1640
 
 
1641
  /*
 
1642
    Check that table with given name does not already
 
1643
    exist in any storage engine. In such a case it should
 
1644
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1645
    unless user specified CREATE TABLE IF EXISTS
 
1646
    The LOCK_open mutex has been locked to make sure no
 
1647
    one else is attempting to discover the table. Since
 
1648
    it's not on disk as a frm cursor, no one could be using it!
 
1649
  */
 
1650
  if (! lex_identified_temp_table)
 
1651
  {
 
1652
    int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
 
1653
 
 
1654
    switch (retcode)
 
1655
    {
 
1656
      case ENOENT:
 
1657
        /* Normal case, no table exists. we can go and create it */
 
1658
        break;
 
1659
      case EEXIST:
 
1660
        if (is_if_not_exists)
 
1661
        {
 
1662
          error= false;
 
1663
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1664
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1665
                              identifier.getTableName());
 
1666
          create_info->table_existed= 1;                // Mark that table existed
 
1667
          goto unlock_and_end;
 
1668
        }
 
1669
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1670
        goto unlock_and_end;
 
1671
      default:
 
1672
        my_error(retcode, MYF(0), identifier.getTableName());
 
1673
        goto unlock_and_end;
 
1674
    }
 
1675
  }
 
1676
 
 
1677
  session->set_proc_info("creating table");
 
1678
  create_info->table_existed= 0;                // Mark that table is created
 
1679
 
 
1680
  create_info->table_options=db_options;
 
1681
 
 
1682
  if (rea_create_table(session, identifier,
 
1683
                       table_proto,
 
1684
                       create_info, alter_info->create_list,
 
1685
                       key_count, key_info_buffer))
 
1686
    goto unlock_and_end;
 
1687
 
 
1688
  if (lex_identified_temp_table)
 
1689
  {
 
1690
    /* Open table and put in temporary table list */
 
1691
    if (!(session->open_temporary_table(identifier)))
 
1692
    {
 
1693
      (void) session->rm_temporary_table(create_info->db_type, identifier);
 
1694
      goto unlock_and_end;
 
1695
    }
 
1696
  }
 
1697
 
 
1698
  /*
 
1699
    Don't write statement if:
 
1700
    - It is an internal temporary table,
 
1701
    - Row-based logging is used and it we are creating a temporary table, or
 
1702
    - The binary log is not open.
 
1703
    Otherwise, the statement shall be binlogged.
 
1704
   */
 
1705
  if (!internal_tmp_table && ! lex_identified_temp_table)
 
1706
    write_bin_log(session, session->query, session->query_length);
 
1707
  error= false;
 
1708
unlock_and_end:
 
1709
  pthread_mutex_unlock(&LOCK_open);
 
1710
 
 
1711
err:
 
1712
  session->set_proc_info("After create");
 
1713
  delete cursor;
 
1714
  return(error);
1508
1715
}
1509
1716
 
1510
1717
 
1511
1718
/*
1512
1719
  Database locking aware wrapper for mysql_create_table_no_lock(),
1513
1720
*/
 
1721
 
1514
1722
bool mysql_create_table(Session *session,
1515
 
                        const TableIdentifier &identifier,
 
1723
                        TableIdentifier &identifier,
1516
1724
                        HA_CREATE_INFO *create_info,
1517
 
                        message::Table &table_proto,
 
1725
                        message::Table *table_proto,
1518
1726
                        AlterInfo *alter_info,
1519
1727
                        bool internal_tmp_table,
1520
1728
                        uint32_t select_field_count,
1521
1729
                        bool is_if_not_exists)
1522
1730
{
1523
 
  if (identifier.isTmp())
1524
 
  {
1525
 
    return mysql_create_table_no_lock(session,
1526
 
                                      identifier,
1527
 
                                      create_info,
1528
 
                                      table_proto,
1529
 
                                      alter_info,
1530
 
                                      internal_tmp_table,
1531
 
                                      select_field_count,
1532
 
                                      is_if_not_exists);
1533
 
  }
1534
 
 
1535
 
  return drizzle_create_table(session,
1536
 
                              identifier,
1537
 
                              create_info,
1538
 
                              table_proto,
1539
 
                              alter_info,
1540
 
                              internal_tmp_table,
1541
 
                              select_field_count,
1542
 
                              is_if_not_exists);
 
1731
  Table *name_lock= NULL;
 
1732
  bool result;
 
1733
  bool lex_identified_temp_table=
 
1734
    (table_proto->type() == drizzled::message::Table::TEMPORARY);
 
1735
 
 
1736
  if (! lex_identified_temp_table)
 
1737
  {
 
1738
    if (session->lock_table_name_if_not_cached(identifier.getDBName(),
 
1739
                                               identifier.getTableName(),
 
1740
                                               &name_lock))
 
1741
    {
 
1742
      result= true;
 
1743
      goto unlock;
 
1744
    }
 
1745
    if (name_lock == NULL)
 
1746
    {
 
1747
      if (is_if_not_exists)
 
1748
      {
 
1749
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1750
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1751
                            identifier.getTableName());
 
1752
        create_info->table_existed= 1;
 
1753
        result= false;
 
1754
      }
 
1755
      else
 
1756
      {
 
1757
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1758
        result= true;
 
1759
      }
 
1760
      goto unlock;
 
1761
    }
 
1762
  }
 
1763
 
 
1764
  result= mysql_create_table_no_lock(session,
 
1765
                                     identifier,
 
1766
                                     create_info,
 
1767
                                     table_proto,
 
1768
                                     alter_info,
 
1769
                                     internal_tmp_table,
 
1770
                                     select_field_count,
 
1771
                                     is_if_not_exists);
 
1772
 
 
1773
unlock:
 
1774
  if (name_lock)
 
1775
  {
 
1776
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
 
1777
    session->unlink_open_table(name_lock);
 
1778
    pthread_mutex_unlock(&LOCK_open);
 
1779
  }
 
1780
 
 
1781
  return(result);
1543
1782
}
1544
1783
 
1545
1784
 
1548
1787
**/
1549
1788
 
1550
1789
static bool
1551
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1790
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1552
1791
{
1553
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1792
  for (KEY *key=start ; key != end ; key++)
1554
1793
    if (!my_strcasecmp(system_charset_info,name,key->name))
1555
1794
      return 1;
1556
1795
  return 0;
1558
1797
 
1559
1798
 
1560
1799
static char *
1561
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1800
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1562
1801
{
1563
1802
  char buff[MAX_FIELD_NAME],*buff_end;
1564
1803
 
1576
1815
  for (uint32_t i=2 ; i< 100; i++)
1577
1816
  {
1578
1817
    *buff_end= '_';
1579
 
    internal::int10_to_str(i, buff_end+1, 10);
 
1818
    int10_to_str(i, buff_end+1, 10);
1580
1819
    if (!check_if_keyname_exists(buff,start,end))
1581
 
      return memory::sql_strdup(buff);
 
1820
      return sql_strdup(buff);
1582
1821
  }
1583
1822
  return (char*) "not_specified";               // Should never happen
1584
1823
}
1593
1832
 
1594
1833
  SYNOPSIS
1595
1834
    mysql_rename_table()
1596
 
      session
1597
1835
      base                      The plugin::StorageEngine handle.
1598
1836
      old_db                    The old database name.
1599
1837
      old_name                  The old table name.
1600
1838
      new_db                    The new database name.
1601
1839
      new_name                  The new table name.
 
1840
      flags                     flags for build_table_filename().
 
1841
                                FN_FROM_IS_TMP old_name is temporary.
 
1842
                                FN_TO_IS_TMP   new_name is temporary.
1602
1843
 
1603
1844
  RETURN
1604
1845
    false   OK
1606
1847
*/
1607
1848
 
1608
1849
bool
1609
 
mysql_rename_table(Session &session,
1610
 
                   plugin::StorageEngine *base,
1611
 
                   const TableIdentifier &from,
1612
 
                   const TableIdentifier &to)
 
1850
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
 
1851
                   const char *old_name, const char *new_db,
 
1852
                   const char *new_name, uint32_t flags)
1613
1853
{
 
1854
  Session *session= current_session;
 
1855
  char from[FN_REFLEN], to[FN_REFLEN];
 
1856
  char *from_base= from, *to_base= to;
1614
1857
  int error= 0;
1615
1858
 
1616
1859
  assert(base);
1617
1860
 
1618
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
1861
  build_table_filename(from, sizeof(from), old_db, old_name,
 
1862
                       flags & FN_FROM_IS_TMP);
 
1863
  build_table_filename(to, sizeof(to), new_db, new_name,
 
1864
                       flags & FN_TO_IS_TMP);
 
1865
 
 
1866
  if (!(error= base->renameTable(session, from_base, to_base)))
1619
1867
  {
1620
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1621
 
    return true;
 
1868
    if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1869
       && rename_table_proto_file(from_base, to_base))
 
1870
    {
 
1871
      error= my_errno;
 
1872
      base->renameTable(session, to_base, from_base);
 
1873
    }
1622
1874
  }
1623
1875
 
1624
 
  error= base->renameTable(session, from, to);
1625
 
 
1626
1876
  if (error == HA_ERR_WRONG_COMMAND)
1627
 
  {
1628
1877
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1629
 
  }
1630
1878
  else if (error)
1631
 
  {
1632
 
    std::string from_path;
1633
 
    std::string to_path;
1634
 
 
1635
 
    from.getSQLPath(from_path);
1636
 
    to.getSQLPath(to_path);
1637
 
 
1638
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1639
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1640
 
 
1641
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1642
 
  }
1643
 
 
1644
 
  return error ? true : false; 
 
1879
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
1880
  return(error != 0);
1645
1881
}
1646
1882
 
1647
1883
 
1660
1896
   the table is closed.
1661
1897
 
1662
1898
  PREREQUISITES
1663
 
    Lock on table::Cache::singleton().mutex()
 
1899
    Lock on LOCK_open
1664
1900
    Win32 clients must also have a WRITE LOCK on the table !
1665
1901
*/
1666
1902
 
1668
1904
                              enum ha_extra_function function)
1669
1905
{
1670
1906
 
1671
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1907
  safe_mutex_assert_owner(&LOCK_open);
1672
1908
 
1673
1909
  table->cursor->extra(function);
1674
1910
  /* Mark all tables that are in use as 'old' */
1675
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1911
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1676
1912
 
1677
1913
  /* Wait until all there are no other threads that has this table open */
1678
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1679
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
1914
  remove_table_from_cache(session, table->s->db.str,
 
1915
                          table->s->table_name.str,
 
1916
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1680
1917
}
1681
1918
 
1682
1919
/*
1692
1929
    reopen the table.
1693
1930
 
1694
1931
  PREREQUISITES
1695
 
    Lock on table::Cache::singleton().mutex()
 
1932
    Lock on LOCK_open
1696
1933
    Win32 clients must also have a WRITE LOCK on the table !
1697
1934
*/
1698
1935
 
1703
1940
  /* Close lock if this is not got with LOCK TABLES */
1704
1941
  if (lock)
1705
1942
  {
1706
 
    unlockTables(lock);
 
1943
    mysql_unlock_tables(this, lock);
1707
1944
    lock= NULL;                 // Start locked threads
1708
1945
  }
1709
1946
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1710
1947
  unlink_open_table(table);
1711
1948
 
1712
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1713
 
  locking::broadcast_refresh();
 
1949
  /* When lock on LOCK_open is freed other threads can continue */
 
1950
  broadcast_refresh();
1714
1951
}
1715
1952
 
1716
1953
/*
1724
1961
                              const char *operator_name,
1725
1962
                              thr_lock_type lock_type,
1726
1963
                              bool open_for_modify,
 
1964
                              bool no_warnings_for_error,
 
1965
                              uint32_t extra_open_options,
 
1966
                              int (*prepare_func)(Session *, TableList *,
 
1967
                                                  HA_CHECK_OPT *),
1727
1968
                              int (Cursor::*operator_func)(Session *,
1728
1969
                                                            HA_CHECK_OPT *))
1729
1970
{
1733
1974
  Item *item;
1734
1975
  LEX *lex= session->lex;
1735
1976
  int result_code= 0;
1736
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1737
1977
  const CHARSET_INFO * const cs= system_charset_info;
1738
1978
 
1739
1979
  if (! session->endActiveTransaction())
1754
1994
  for (table= tables; table; table= table->next_local)
1755
1995
  {
1756
1996
    char table_name[NAME_LEN*2+2];
 
1997
    char* db = table->db;
1757
1998
    bool fatal_error=0;
1758
1999
 
1759
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
2000
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2001
    session->open_options|= extra_open_options;
1760
2002
    table->lock_type= lock_type;
1761
2003
    /* open only one table from local list of command */
1762
2004
    {
1769
2011
      /*
1770
2012
        Time zone tables and SP tables can be add to lex->query_tables list,
1771
2013
        so it have to be prepared.
1772
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2014
        TODO: Investigate if we can put extra tables into argument instead of
 
2015
        using lex->query_tables
1773
2016
      */
1774
2017
      lex->query_tables= table;
1775
2018
      lex->query_tables_last= &table->next_global;
1776
2019
      lex->query_tables_own_last= 0;
1777
 
      session->no_warnings_for_error= 0;
 
2020
      session->no_warnings_for_error= no_warnings_for_error;
1778
2021
 
1779
2022
      session->openTablesLock(table);
1780
2023
      session->no_warnings_for_error= 0;
1781
2024
      table->next_global= save_next_global;
1782
2025
      table->next_local= save_next_local;
 
2026
      session->open_options&= ~extra_open_options;
 
2027
    }
 
2028
 
 
2029
    if (prepare_func)
 
2030
    {
 
2031
      switch ((*prepare_func)(session, table, check_opt)) {
 
2032
      case  1:           // error, message written to net
 
2033
        ha_autocommit_or_rollback(session, 1);
 
2034
        session->endTransaction(ROLLBACK);
 
2035
        session->close_thread_tables();
 
2036
        continue;
 
2037
      case -1:           // error, message could be written to net
 
2038
        goto err;
 
2039
      default:           // should be 0 otherwise
 
2040
        ;
 
2041
      }
1783
2042
    }
1784
2043
 
1785
2044
    /*
1809
2068
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1810
2069
                       table_name);
1811
2070
      session->client->store(buff, length);
1812
 
      transaction_services.autocommitOrRollback(session, false);
 
2071
      ha_autocommit_or_rollback(session, 0);
1813
2072
      session->endTransaction(COMMIT);
1814
2073
      session->close_thread_tables();
1815
2074
      lex->reset_query_tables_list(false);
1820
2079
    }
1821
2080
 
1822
2081
    /* Close all instances of the table to allow repair to rename files */
1823
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2082
    if (lock_type == TL_WRITE && table->table->s->version)
1824
2083
    {
1825
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1826
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1827
 
                                                  "Waiting to get writelock");
1828
 
      session->abortLock(table->table);
1829
 
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1830
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
2084
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2085
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
2086
                                              "Waiting to get writelock");
 
2087
      mysql_lock_abort(session,table->table);
 
2088
      remove_table_from_cache(session, table->table->s->db.str,
 
2089
                              table->table->s->table_name.str,
 
2090
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2091
                              RTFC_CHECK_KILLED_FLAG);
1831
2092
      session->exit_cond(old_message);
1832
 
      if (session->getKilled())
 
2093
      if (session->killed)
1833
2094
        goto err;
1834
2095
      open_for_modify= 0;
1835
2096
    }
1836
2097
 
 
2098
    if (table->table->s->crashed && operator_func == &Cursor::ha_check)
 
2099
    {
 
2100
      session->client->store(table_name);
 
2101
      session->client->store(operator_name);
 
2102
      session->client->store(STRING_WITH_LEN("warning"));
 
2103
      session->client->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2104
      if (session->client->flush())
 
2105
        goto err;
 
2106
    }
 
2107
 
1837
2108
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
1838
2109
 
1839
2110
send_result:
1916
2187
    if (table->table)
1917
2188
    {
1918
2189
      if (fatal_error)
1919
 
      {
1920
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1921
 
      }
 
2190
        table->table->s->version=0;               // Force close of table
1922
2191
      else if (open_for_modify)
1923
2192
      {
1924
 
        if (table->table->getShare()->getType())
1925
 
        {
 
2193
        if (table->table->s->tmp_table)
1926
2194
          table->table->cursor->info(HA_STATUS_CONST);
1927
 
        }
1928
2195
        else
1929
2196
        {
1930
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1931
 
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1932
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
2197
          pthread_mutex_lock(&LOCK_open);
 
2198
          remove_table_from_cache(session, table->table->s->db.str,
 
2199
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2200
          pthread_mutex_unlock(&LOCK_open);
1933
2201
        }
1934
2202
      }
1935
2203
    }
1936
 
    transaction_services.autocommitOrRollback(session, false);
 
2204
    ha_autocommit_or_rollback(session, 0);
1937
2205
    session->endTransaction(COMMIT);
1938
2206
    session->close_thread_tables();
1939
2207
    table->table=0;                             // For query cache
1945
2213
  return(false);
1946
2214
 
1947
2215
err:
1948
 
  transaction_services.autocommitOrRollback(session, true);
 
2216
  ha_autocommit_or_rollback(session, 1);
1949
2217
  session->endTransaction(ROLLBACK);
1950
2218
  session->close_thread_tables();                       // Shouldn't be needed
1951
2219
  if (table)
1953
2221
  return(true);
1954
2222
}
1955
2223
 
1956
 
  /*
1957
 
    Create a new table by copying from source table
1958
 
 
1959
 
    Altough exclusive name-lock on target table protects us from concurrent
1960
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
1961
 
    to plugin::StorageEngine::createTable() in critical section protected by
1962
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1963
 
    disregard name-locks, like I_S implementation, for example. This is a
1964
 
    temporary and should not be copied. Instead we should fix our code to
1965
 
    always honor name-locks.
1966
 
 
1967
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1968
 
    during the call to plugin::StorageEngine::createTable().
1969
 
    See bug #28614 for more info.
1970
 
  */
1971
 
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
 
                                 const TableIdentifier &destination_identifier,
1973
 
                                 const TableIdentifier &src_table,
1974
 
                                 bool is_engine_set)
1975
 
{
1976
 
  int protoerr= EEXIST;
1977
 
  message::Table new_proto;
1978
 
  message::table::shared_ptr src_proto;
1979
 
 
1980
 
  protoerr= plugin::StorageEngine::getTableDefinition(session,
1981
 
                                                      src_table,
1982
 
                                                      src_proto);
1983
 
  new_proto.CopyFrom(*src_proto);
1984
 
 
1985
 
  if (destination_identifier.isTmp())
1986
 
  {
1987
 
    new_proto.set_type(message::Table::TEMPORARY);
1988
 
  }
1989
 
  else
1990
 
  {
1991
 
    new_proto.set_type(message::Table::STANDARD);
1992
 
  }
1993
 
 
1994
 
  if (is_engine_set)
1995
 
  {
1996
 
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
1997
 
  }
1998
 
 
1999
 
  { // We now do a selective copy of elements on to the new table.
2000
 
    new_proto.set_name(create_table_proto.name());
2001
 
    new_proto.set_schema(create_table_proto.schema());
2002
 
    new_proto.set_catalog(create_table_proto.catalog());
2003
 
  }
2004
 
 
2005
 
  if (protoerr && protoerr != EEXIST)
2006
 
  {
2007
 
    if (errno == ENOENT)
2008
 
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2009
 
    else
2010
 
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2011
 
 
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  /*
2016
 
    As mysql_truncate don't work on a new table at this stage of
2017
 
    creation, instead create the table directly (for both normal
2018
 
    and temporary tables).
2019
 
  */
2020
 
  int err= plugin::StorageEngine::createTable(session,
2021
 
                                              destination_identifier,
2022
 
                                              new_proto);
2023
 
 
2024
 
  if (err == false && not destination_identifier.isTmp())
2025
 
  {
2026
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2027
 
    transaction_services.createTable(&session, new_proto);
2028
 
  }
2029
 
 
2030
 
  return err ? false : true;
2031
 
}
2032
 
 
2033
2224
/*
2034
2225
  Create a table identical to the specified table
2035
2226
 
2045
2236
    true  error
2046
2237
*/
2047
2238
 
2048
 
bool mysql_create_like_table(Session* session,
2049
 
                             const TableIdentifier &destination_identifier,
2050
 
                             TableList* table, TableList* src_table,
2051
 
                             message::Table &create_table_proto,
 
2239
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2240
                             drizzled::message::Table& create_table_proto,
 
2241
                             drizzled::plugin::StorageEngine *engine_arg,
2052
2242
                             bool is_if_not_exists,
2053
2243
                             bool is_engine_set)
2054
2244
{
 
2245
  Table *name_lock= 0;
 
2246
  char src_path[FN_REFLEN];
 
2247
  char *db= table->db;
 
2248
  char *table_name= table->table_name;
 
2249
  int  err;
2055
2250
  bool res= true;
2056
2251
  uint32_t not_used;
 
2252
  message::Table src_proto;
 
2253
  bool lex_identified_temp_table=
 
2254
    (create_table_proto.type() == drizzled::message::Table::TEMPORARY);
2057
2255
 
2058
2256
  /*
2059
2257
    By opening source table we guarantee that it exists and no concurrent
2067
2265
  if (session->open_tables_from_list(&src_table, &not_used))
2068
2266
    return true;
2069
2267
 
2070
 
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2071
 
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2072
 
 
2073
 
 
 
2268
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
 
2269
 
 
2270
 
 
2271
  TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ?
 
2272
                                         (engine_arg->check_flag(HTON_BIT_DOES_TRANSACTIONS) ? TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE) :
 
2273
                                         NO_TMP_TABLE);
2074
2274
 
2075
2275
  /*
2076
2276
    Check that destination tables does not exist. Note that its name
2077
2277
    was already checked when it was added to the table list.
2078
 
 
2079
 
    For temporary tables we don't aim to grab locks.
2080
 
  */
2081
 
  bool table_exists= false;
2082
 
  if (destination_identifier.isTmp())
2083
 
  {
2084
 
    if (session->find_temporary_table(destination_identifier))
2085
 
    {
2086
 
      table_exists= true;
2087
 
    }
2088
 
    else
2089
 
    {
2090
 
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
 
                                             src_identifier, is_engine_set);
2092
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2093
 
      {
2094
 
        (void) session->rm_temporary_table(destination_identifier, true);
2095
 
      }
2096
 
      else if (not session->open_temporary_table(destination_identifier))
2097
 
      {
2098
 
        // We created, but we can't open... also, a hack.
2099
 
        (void) session->rm_temporary_table(destination_identifier, true);
2100
 
      }
2101
 
      else
2102
 
      {
2103
 
        res= false;
2104
 
      }
2105
 
    }
2106
 
  }
2107
 
  else // Standard table which will require locks.
2108
 
  {
2109
 
    Table *name_lock= 0;
2110
 
 
2111
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2112
 
    {
2113
 
      if (name_lock)
2114
 
      {
2115
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2116
 
        session->unlink_open_table(name_lock);
2117
 
      }
2118
 
 
2119
 
      return res;
2120
 
    }
2121
 
 
2122
 
    if (not name_lock)
2123
 
    {
2124
 
      table_exists= true;
2125
 
    }
2126
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2127
 
    {
2128
 
      table_exists= true;
2129
 
    }
2130
 
    else // Otherwise we create the table
2131
 
    {
2132
 
      bool was_created;
2133
 
      {
2134
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2135
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2136
 
                                               src_identifier, is_engine_set);
2137
 
      }
2138
 
 
2139
 
      // So we blew the creation of the table, and we scramble to clean up
2140
 
      // anything that might have been created (read... it is a hack)
2141
 
      if (not was_created)
2142
 
      {
2143
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2144
 
      } 
2145
 
      else
2146
 
      {
2147
 
        res= false;
2148
 
      }
2149
 
    }
2150
 
 
2151
 
    if (name_lock)
2152
 
    {
2153
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2154
 
      session->unlink_open_table(name_lock);
2155
 
    }
2156
 
  }
2157
 
 
2158
 
  if (table_exists)
2159
 
  {
2160
 
    if (is_if_not_exists)
2161
 
    {
2162
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
 
      snprintf(warn_buff, sizeof(warn_buff),
2164
 
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2165
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2166
 
                   ER_TABLE_EXISTS_ERROR,warn_buff);
2167
 
      res= false;
2168
 
    }
2169
 
    else
2170
 
    {
2171
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2172
 
    }
2173
 
  }
2174
 
 
 
2278
  */
 
2279
  if (lex_identified_temp_table)
 
2280
  {
 
2281
    if (session->find_temporary_table(db, table_name))
 
2282
      goto table_exists;
 
2283
  }
 
2284
  else
 
2285
  {
 
2286
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
2287
      goto err;
 
2288
    if (! name_lock)
 
2289
      goto table_exists;
 
2290
 
 
2291
    if (plugin::StorageEngine::getTableDefinition(*session,
 
2292
                                                  destination_identifier) == EEXIST)
 
2293
      goto table_exists;
 
2294
  }
 
2295
 
 
2296
  /*
 
2297
    Create a new table by copying from source table
 
2298
 
 
2299
    Altough exclusive name-lock on target table protects us from concurrent
 
2300
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
2301
    to plugin::StorageEngine::createTable() in critical section protected by
 
2302
    LOCK_open in order to provide minimal atomicity against operations which
 
2303
    disregard name-locks, like I_S implementation, for example. This is a
 
2304
    temporary and should not be copied. Instead we should fix our code to
 
2305
    always honor name-locks.
 
2306
 
 
2307
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
2308
    during the call to plugin::StorageEngine::createTable().
 
2309
    See bug #28614 for more info.
 
2310
  */
 
2311
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2312
  {
 
2313
    int protoerr= EEXIST;
 
2314
 
 
2315
    if (src_table->schema_table)
 
2316
    {
 
2317
      /*
 
2318
        If engine was not specified and we are reading from the I_S, then we need to
 
2319
        toss an error. This should go away later on when we straighten out the
 
2320
        I_S engine.
 
2321
      */
 
2322
      if (! is_engine_set)
 
2323
      {
 
2324
        pthread_mutex_unlock(&LOCK_open);
 
2325
        my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2326
                 "INFORMATION_ENGINE",
 
2327
                 "TEMPORARY");
 
2328
        goto err;
 
2329
      }
 
2330
 
 
2331
      if (create_like_schema_frm(session, src_table, &src_proto))
 
2332
      {
 
2333
        pthread_mutex_unlock(&LOCK_open);
 
2334
        goto err;
 
2335
      }
 
2336
    }
 
2337
    else
 
2338
    {
 
2339
      protoerr= plugin::StorageEngine::getTableDefinition(*session,
 
2340
                                                          src_path,
 
2341
                                                          db,
 
2342
                                                          table_name,
 
2343
                                                          false,
 
2344
                                                          &src_proto);
 
2345
    }
 
2346
 
 
2347
    message::Table new_proto(src_proto);
 
2348
 
 
2349
    if (lex_identified_temp_table)
 
2350
    {
 
2351
      new_proto.set_type(message::Table::TEMPORARY);
 
2352
    }
 
2353
    else
 
2354
    {
 
2355
      new_proto.set_type(message::Table::STANDARD);
 
2356
    }
 
2357
 
 
2358
    if (is_engine_set)
 
2359
    {
 
2360
      message::Table::StorageEngine *protoengine;
 
2361
 
 
2362
      protoengine= new_proto.mutable_engine();
 
2363
      protoengine->set_name(create_table_proto.engine().name());
 
2364
    }
 
2365
 
 
2366
    if (protoerr == EEXIST)
 
2367
    {
 
2368
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
 
2369
                                                                       new_proto.engine().name());
 
2370
 
 
2371
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2372
      {
 
2373
        string dst_proto_path(destination_identifier.getPath());
 
2374
        dst_proto_path.append(".dfe");
 
2375
 
 
2376
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
 
2377
      }
 
2378
      else
 
2379
      {
 
2380
        protoerr= 0;
 
2381
      }
 
2382
    }
 
2383
 
 
2384
    if (protoerr)
 
2385
    {
 
2386
      if (my_errno == ENOENT)
 
2387
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2388
      else
 
2389
        my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), my_errno);
 
2390
      pthread_mutex_unlock(&LOCK_open);
 
2391
      goto err;
 
2392
    }
 
2393
 
 
2394
    /*
 
2395
      As mysql_truncate don't work on a new table at this stage of
 
2396
      creation, instead create the table directly (for both normal
 
2397
      and temporary tables).
 
2398
    */
 
2399
    err= plugin::StorageEngine::createTable(*session,
 
2400
                                            destination_identifier,
 
2401
                                            true, new_proto);
 
2402
  }
 
2403
  pthread_mutex_unlock(&LOCK_open);
 
2404
 
 
2405
  if (lex_identified_temp_table)
 
2406
  {
 
2407
    if (err || !session->open_temporary_table(destination_identifier))
 
2408
    {
 
2409
      (void) session->rm_temporary_table(engine_arg, destination_identifier);
 
2410
      goto err;
 
2411
    }
 
2412
  }
 
2413
  else if (err)
 
2414
  {
 
2415
    (void) quick_rm_table(*session, db,
 
2416
                          table_name, false);
 
2417
    goto err;
 
2418
  }
 
2419
 
 
2420
  /*
 
2421
    We have to write the query before we unlock the tables.
 
2422
  */
 
2423
  {
 
2424
    /*
 
2425
       Since temporary tables are not replicated under row-based
 
2426
       replication, CREATE TABLE ... LIKE ... needs special
 
2427
       treatement.  We have four cases to consider, according to the
 
2428
       following decision table:
 
2429
 
 
2430
           ==== ========= ========= ==============================
 
2431
           Case    Target    Source Write to binary log
 
2432
           ==== ========= ========= ==============================
 
2433
           1       normal    normal Original statement
 
2434
           2       normal temporary Generated statement
 
2435
           3    temporary    normal Nothing
 
2436
           4    temporary temporary Nothing
 
2437
           ==== ========= ========= ==============================
 
2438
    */
 
2439
    if (! lex_identified_temp_table)
 
2440
    {
 
2441
      if (src_table->table->s->tmp_table)               // Case 2
 
2442
      {
 
2443
        char buf[2048];
 
2444
        String query(buf, sizeof(buf), system_charset_info);
 
2445
        query.length(0);  // Have to zero it since constructor doesn't
 
2446
 
 
2447
 
 
2448
        /*
 
2449
          Here we open the destination table, on which we already have
 
2450
          name-lock. This is needed for store_create_info() to work.
 
2451
          The table will be closed by unlink_open_table() at the end
 
2452
          of this function.
 
2453
        */
 
2454
        table->table= name_lock;
 
2455
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2456
        if (session->reopen_name_locked_table(table, false))
 
2457
        {
 
2458
          pthread_mutex_unlock(&LOCK_open);
 
2459
          goto err;
 
2460
        }
 
2461
        pthread_mutex_unlock(&LOCK_open);
 
2462
 
 
2463
        int result= store_create_info(table, &query, is_if_not_exists);
 
2464
 
 
2465
        assert(result == 0); // store_create_info() always return 0
 
2466
        write_bin_log(session, query.ptr(), query.length());
 
2467
      }
 
2468
      else                                      // Case 1
 
2469
        write_bin_log(session, session->query, session->query_length);
 
2470
    }
 
2471
  }
 
2472
 
 
2473
  res= false;
 
2474
  goto err;
 
2475
 
 
2476
table_exists:
 
2477
  if (is_if_not_exists)
 
2478
  {
 
2479
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2480
    snprintf(warn_buff, sizeof(warn_buff),
 
2481
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2482
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2483
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2484
    res= false;
 
2485
  }
 
2486
  else
 
2487
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2488
 
 
2489
err:
 
2490
  if (name_lock)
 
2491
  {
 
2492
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2493
    session->unlink_open_table(name_lock);
 
2494
    pthread_mutex_unlock(&LOCK_open);
 
2495
  }
2175
2496
  return(res);
2176
2497
}
2177
2498
 
2181
2502
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2182
2503
 
2183
2504
  return(mysql_admin_table(session, tables, check_opt,
2184
 
                                "analyze", lock_type, true,
 
2505
                                "analyze", lock_type, 1, 0, 0, 0,
2185
2506
                                &Cursor::ha_analyze));
2186
2507
}
2187
2508
 
2192
2513
 
2193
2514
  return(mysql_admin_table(session, tables, check_opt,
2194
2515
                                "check", lock_type,
2195
 
                                false,
 
2516
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
2196
2517
                                &Cursor::ha_check));
2197
2518
}
2198
2519
 
2199
 
} /* namespace drizzled */
 
2520
/*
 
2521
  Recreates tables by calling drizzled::alter_table().
 
2522
 
 
2523
  SYNOPSIS
 
2524
    mysql_recreate_table()
 
2525
    session                     Thread Cursor
 
2526
    tables              Tables to recreate
 
2527
 
 
2528
 RETURN
 
2529
    Like drizzled::alter_table().
 
2530
*/
 
2531
bool mysql_recreate_table(Session *session, TableList *table_list)
 
2532
{
 
2533
  HA_CREATE_INFO create_info;
 
2534
  AlterInfo alter_info;
 
2535
  message::Table table_proto;
 
2536
 
 
2537
  assert(!table_list->next_global);
 
2538
  /*
 
2539
    table_list->table has been closed and freed. Do not reference
 
2540
    uninitialized data. open_tables() could fail.
 
2541
  */
 
2542
  table_list->table= NULL;
 
2543
 
 
2544
  memset(&create_info, 0, sizeof(create_info));
 
2545
  create_info.row_type=ROW_TYPE_NOT_USED;
 
2546
  create_info.default_table_charset=default_charset_info;
 
2547
  /* Force alter table to recreate table */
 
2548
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
2549
  alter_info.flags.set(ALTER_RECREATE);
 
2550
  return(alter_table(session, NULL, NULL, &create_info, &table_proto,
 
2551
                     table_list, &alter_info, 0,
 
2552
                     (order_st *) 0, 0));
 
2553
}
 
2554
 
 
2555
 
 
2556
bool mysql_checksum_table(Session *session, TableList *tables,
 
2557
                          HA_CHECK_OPT *)
 
2558
{
 
2559
  TableList *table;
 
2560
  List<Item> field_list;
 
2561
  Item *item;
 
2562
 
 
2563
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
2564
  item->maybe_null= 1;
 
2565
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
2566
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
2567
  item->maybe_null= 1;
 
2568
  if (session->client->sendFields(&field_list))
 
2569
    return true;
 
2570
 
 
2571
  /* Open one table after the other to keep lock time as short as possible. */
 
2572
  for (table= tables; table; table= table->next_local)
 
2573
  {
 
2574
    char table_name[NAME_LEN*2+2];
 
2575
    Table *t;
 
2576
 
 
2577
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2578
 
 
2579
    t= table->table= session->openTableLock(table, TL_READ);
 
2580
    session->clear_error();                     // these errors shouldn't get client
 
2581
 
 
2582
    session->client->store(table_name);
 
2583
 
 
2584
    if (!t)
 
2585
    {
 
2586
      /* Table didn't exist */
 
2587
      session->client->store();
 
2588
      session->clear_error();
 
2589
    }
 
2590
    else
 
2591
    {
 
2592
      /**
 
2593
        @note if the engine keeps a checksum then we return the checksum, otherwise we calculate
 
2594
      */
 
2595
      if (t->cursor->ha_table_flags() & HA_HAS_CHECKSUM)
 
2596
        session->client->store((uint64_t)t->cursor->checksum());
 
2597
      else
 
2598
      {
 
2599
        /* calculating table's checksum */
 
2600
        ha_checksum crc= 0;
 
2601
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2602
 
 
2603
        t->use_all_columns();
 
2604
 
 
2605
        if (t->cursor->ha_rnd_init(1))
 
2606
          session->client->store();
 
2607
        else
 
2608
        {
 
2609
          for (;;)
 
2610
          {
 
2611
            ha_checksum row_crc= 0;
 
2612
            int error= t->cursor->rnd_next(t->record[0]);
 
2613
            if (unlikely(error))
 
2614
            {
 
2615
              if (error == HA_ERR_RECORD_DELETED)
 
2616
                continue;
 
2617
              break;
 
2618
            }
 
2619
            if (t->s->null_bytes)
 
2620
            {
 
2621
              /* fix undefined null bits */
 
2622
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
2623
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
2624
                t->record[0][0] |= 1;
 
2625
 
 
2626
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
2627
            }
 
2628
 
 
2629
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
2630
            {
 
2631
              Field *f= t->field[i];
 
2632
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
2633
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
2634
              {
 
2635
                String tmp;
 
2636
                f->val_str(&tmp);
 
2637
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
2638
              }
 
2639
              else
 
2640
                row_crc= my_checksum(row_crc, f->ptr,
 
2641
                                     f->pack_length());
 
2642
            }
 
2643
 
 
2644
            crc+= row_crc;
 
2645
          }
 
2646
          session->client->store((uint64_t)crc);
 
2647
          t->cursor->ha_rnd_end();
 
2648
        }
 
2649
      }
 
2650
      session->clear_error();
 
2651
      session->close_thread_tables();
 
2652
      table->table=0;                           // For query cache
 
2653
    }
 
2654
    if (session->client->flush())
 
2655
      goto err;
 
2656
  }
 
2657
 
 
2658
  session->my_eof();
 
2659
  return(false);
 
2660
 
 
2661
 err:
 
2662
  session->close_thread_tables();                       // Shouldn't be needed
 
2663
  if (table)
 
2664
    table->table=0;
 
2665
  return(true);
 
2666
}