~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2009-11-18 06:24:48 UTC
  • mfrom: (1220.1.15 staging)
  • Revision ID: brian@gaz-20091118062448-o36lo3yv81sc6u9z
Merge Brian + Stewart

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"
50
 
#include "drizzled/plugin/storage_engine.h"
 
37
 
 
38
#include "drizzled/statement/alter_table.h" /* for drizzled::create_like_schema_frm, which will die soon */
51
39
 
52
40
#include <algorithm>
53
 
#include <sstream>
54
 
 
55
 
#include <boost/unordered_set.hpp>
56
41
 
57
42
using namespace std;
58
 
 
59
 
namespace drizzled
60
 
{
61
 
 
62
 
bool is_primary_key(KeyInfo *key_info)
 
43
using namespace drizzled;
 
44
 
 
45
static const char hexchars[]= "0123456789abcdef";
 
46
bool is_primary_key(KEY *key_info)
63
47
{
64
48
  static const char * primary_key_name="PRIMARY";
65
49
  return (strcmp(key_info->name, primary_key_name)==0);
74
58
    return NULL;
75
59
}
76
60
 
77
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
78
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
 
61
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
62
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
79
63
 
80
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
81
65
 
82
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
 
66
void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
83
67
{
84
68
  /*
85
69
    If the table character set was not given explicitly,
86
70
    let's fetch the database default character set and
87
71
    apply it to the table.
88
72
  */
89
 
  identifier::Schema identifier(db);
90
73
  if (create_info->default_table_charset == NULL)
91
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
 
74
    create_info->default_table_charset= get_default_db_collation(db);
 
75
}
 
76
 
 
77
/*
 
78
  Translate a cursor name to a table name (WL #1324).
 
79
 
 
80
  SYNOPSIS
 
81
    filename_to_tablename()
 
82
      from                      The cursor name
 
83
      to                OUT     The table name
 
84
      to_length                 The size of the table name buffer.
 
85
 
 
86
  RETURN
 
87
    Table name length.
 
88
*/
 
89
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
 
90
{
 
91
  uint32_t length= 0;
 
92
 
 
93
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
 
94
  {
 
95
    /* Temporary table name. */
 
96
    length= strlen(strncpy(to, from, to_length));
 
97
  }
 
98
  else
 
99
  {
 
100
    for (; *from  && length < to_length; length++, from++)
 
101
    {
 
102
      if (*from != '@')
 
103
      {
 
104
        to[length]= *from;
 
105
        continue;
 
106
      }
 
107
      /* We've found an escaped char - skip the @ */
 
108
      from++;
 
109
      to[length]= 0;
 
110
      /* There will be a two-position hex-char version of the char */
 
111
      for (int x=1; x >= 0; x--)
 
112
      {
 
113
        if (*from >= '0' && *from <= '9')
 
114
          to[length] += ((*from++ - '0') << (4 * x));
 
115
        else if (*from >= 'a' && *from <= 'f')
 
116
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
117
      }
 
118
      /* Backup because we advanced extra in the inner loop */
 
119
      from--;
 
120
    } 
 
121
  }
 
122
 
 
123
  return length;
 
124
}
 
125
 
 
126
 
 
127
/*
 
128
  Translate a table name to a cursor name (WL #1324).
 
129
 
 
130
  SYNOPSIS
 
131
    tablename_to_filename()
 
132
      from                      The table name
 
133
      to                OUT     The cursor name
 
134
      to_length                 The size of the cursor name buffer.
 
135
 
 
136
  RETURN
 
137
    true if errors happen. false on success.
 
138
*/
 
139
bool tablename_to_filename(const char *from, char *to, size_t to_length)
 
140
{
 
141
  
 
142
  size_t length= 0;
 
143
  for (; *from  && length < to_length; length++, from++)
 
144
  {
 
145
    if ((*from >= '0' && *from <= '9') ||
 
146
        (*from >= 'A' && *from <= 'Z') ||
 
147
        (*from >= 'a' && *from <= 'z') ||
 
148
/* OSX defines an extra set of high-bit and multi-byte characters
 
149
   that cannot be used on the filesystem. Instead of trying to sort
 
150
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
151
   It won't really hurt anything - it'll just make some filenames ugly. */
 
152
#if !defined(TARGET_OS_OSX)
 
153
        ((unsigned char)*from >= 128) ||
 
154
#endif
 
155
        (*from == '_') ||
 
156
        (*from == ' ') ||
 
157
        (*from == '-'))
 
158
    {
 
159
      to[length]= *from;
 
160
      continue;
 
161
    }
 
162
   
 
163
    if (length + 3 >= to_length)
 
164
      return true;
 
165
 
 
166
    /* We need to escape this char in a way that can be reversed */
 
167
    to[length++]= '@';
 
168
    to[length++]= hexchars[(*from >> 4) & 15];
 
169
    to[length]= hexchars[(*from) & 15];
 
170
  }
 
171
 
 
172
  if (check_if_legal_tablename(to) &&
 
173
      length + 4 < to_length)
 
174
  {
 
175
    memcpy(to + length, "@@@", 4);
 
176
    length+= 3;
 
177
  }
 
178
  return false;
 
179
}
 
180
 
 
181
 
 
182
/*
 
183
  Creates path to a cursor: drizzle_data_dir/db/table.ext
 
184
 
 
185
  SYNOPSIS
 
186
   build_table_filename()
 
187
     buff                       Where to write result
 
188
                                This may be the same as table_name.
 
189
     bufflen                    buff size
 
190
     db                         Database name
 
191
     table_name                 Table name
 
192
     ext                        File extension.
 
193
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
194
                                table_name is temporary, do not change.
 
195
 
 
196
  NOTES
 
197
 
 
198
    Uses database and table name, and extension to create
 
199
    a cursor name in drizzle_data_dir. Database and table
 
200
    names are converted from system_charset_info into "fscs".
 
201
    Unless flags indicate a temporary table name.
 
202
    'db' is always converted.
 
203
    'ext' is not converted.
 
204
 
 
205
    The conversion suppression is required for ALTER Table. This
 
206
    statement creates intermediate tables. These are regular
 
207
    (non-temporary) tables with a temporary name. Their path names must
 
208
    be derivable from the table name. So we cannot use
 
209
    build_tmptable_filename() for them.
 
210
 
 
211
  RETURN
 
212
    path length on success, 0 on failure
 
213
*/
 
214
 
 
215
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
 
216
{
 
217
  char dbbuff[FN_REFLEN];
 
218
  char tbbuff[FN_REFLEN];
 
219
  bool conversion_error= false;
 
220
 
 
221
  memset(tbbuff, 0, sizeof(tbbuff));
 
222
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
223
    strncpy(tbbuff, table_name, sizeof(tbbuff));
 
224
  else
 
225
  {
 
226
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
227
    if (conversion_error)
 
228
    {
 
229
      errmsg_printf(ERRMSG_LVL_ERROR,
 
230
                    _("Table name cannot be encoded and fit within filesystem "
 
231
                      "name length restrictions."));
 
232
      return 0;
 
233
    }
 
234
  }
 
235
  memset(dbbuff, 0, sizeof(dbbuff));
 
236
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
237
  if (conversion_error)
 
238
  {
 
239
    errmsg_printf(ERRMSG_LVL_ERROR,
 
240
                  _("Schema name cannot be encoded and fit within filesystem "
 
241
                    "name length restrictions."));
 
242
    return 0;
 
243
  }
 
244
   
 
245
 
 
246
  int rootdir_len= strlen(FN_ROOTDIR);
 
247
  string table_path(drizzle_data_home);
 
248
  int without_rootdir= table_path.length()-rootdir_len;
 
249
 
 
250
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
251
  if (without_rootdir >= 0)
 
252
  {
 
253
    const char *tmp= table_path.c_str()+without_rootdir;
 
254
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
255
      table_path.append(FN_ROOTDIR);
 
256
  }
 
257
 
 
258
  table_path.append(dbbuff);
 
259
  table_path.append(FN_ROOTDIR);
 
260
  table_path.append(tbbuff);
 
261
 
 
262
  if (bufflen < table_path.length())
 
263
    return 0;
 
264
 
 
265
  strcpy(buff, table_path.c_str());
 
266
 
 
267
  return table_path.length();
 
268
}
 
269
 
 
270
 
 
271
/*
 
272
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
 
273
 
 
274
  SYNOPSIS
 
275
   build_tmptable_filename()
 
276
     session                    The thread handle.
 
277
     buff                       Where to write result
 
278
     bufflen                    buff size
 
279
 
 
280
  NOTES
 
281
 
 
282
    Uses current_pid, thread_id, and tmp_table counter to create
 
283
    a cursor name in drizzle_tmpdir.
 
284
 
 
285
  RETURN
 
286
    path length on success, 0 on failure
 
287
*/
 
288
 
 
289
static uint32_t build_tmptable_filename(Session* session,
 
290
                                        char *buff, size_t bufflen)
 
291
{
 
292
  uint32_t length;
 
293
  ostringstream path_str, post_tmpdir_str;
 
294
  string tmp;
 
295
 
 
296
  path_str << drizzle_tmpdir;
 
297
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
298
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
299
  tmp= post_tmpdir_str.str();
 
300
 
 
301
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
302
 
 
303
  path_str << tmp;
 
304
 
 
305
  if (bufflen < path_str.str().length())
 
306
    length= 0;
 
307
  else
 
308
    length= unpack_filename(buff, path_str.str().c_str());
 
309
 
 
310
  return length;
92
311
}
93
312
 
94
313
/*
106
325
    cursor
107
326
*/
108
327
 
109
 
void write_bin_log(Session *session, const std::string &query)
110
 
{
111
 
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
 
328
void write_bin_log(Session *session,
 
329
                   char const *query, size_t query_length)
 
330
{
 
331
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
332
  replication_services.rawStatement(session, query, query_length);
 
333
}
 
334
 
 
335
 
 
336
/* Should should be refactored to go away */
 
337
static void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
338
{
 
339
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
340
  string built_query;
 
341
 
 
342
  if (if_exists)
 
343
    built_query.append("DROP TABLE IF EXISTS ");
 
344
  else
 
345
    built_query.append("DROP TABLE ");
 
346
 
 
347
  built_query.append("`");
 
348
  if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
 
349
  {
 
350
    built_query.append(db_name);
 
351
    built_query.append("`.`");
 
352
  }
 
353
 
 
354
  built_query.append(table_name);
 
355
  built_query.append("`");
 
356
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
 
357
}
 
358
 
 
359
 
 
360
/*
 
361
 delete (drop) tables.
 
362
 
 
363
  SYNOPSIS
 
364
   mysql_rm_table()
 
365
   session                      Thread handle
 
366
   tables               List of tables to delete
 
367
   if_exists            If 1, don't give error if one table doesn't exists
 
368
 
 
369
  NOTES
 
370
    Will delete all tables that can be deleted and give a compact error
 
371
    messages for tables that could not be deleted.
 
372
    If a table is in use, we will wait for all users to free the table
 
373
    before dropping it
 
374
 
 
375
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
376
    not if under LOCK TABLES.
 
377
 
 
378
  RETURN
 
379
    false OK.  In this case ok packet is sent to user
 
380
    true  Error
 
381
 
 
382
*/
 
383
 
 
384
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
 
385
{
 
386
  bool error, need_start_waiting= false;
 
387
 
 
388
  if (tables && tables->schema_table)
 
389
  {
 
390
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
391
    return(true);
 
392
  }
 
393
 
 
394
  /* mark for close and remove all cached entries */
 
395
 
 
396
  if (!drop_temporary)
 
397
  {
 
398
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
399
      return(true);
 
400
  }
 
401
 
 
402
  /*
 
403
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
404
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
405
    close their tables. This would make a pretty deadlock.
 
406
  */
 
407
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, false);
 
408
 
 
409
  if (need_start_waiting)
 
410
    start_waiting_global_read_lock(session);
 
411
 
 
412
  if (error)
 
413
    return(true);
 
414
  session->my_ok();
 
415
  return(false);
113
416
}
114
417
 
115
418
/*
116
419
  Execute the drop of a normal or temporary table
117
420
 
118
421
  SYNOPSIS
119
 
    rm_table_part2()
 
422
    mysql_rm_table_part2()
120
423
    session                     Thread Cursor
121
424
    tables              Tables to drop
122
425
    if_exists           If set, don't give an error if table doesn't exists.
123
426
                        In this case we give an warning of level 'NOTE'
124
427
    drop_temporary      Only drop temporary tables
 
428
    dont_log_query      Don't write query to log files. This will also not
 
429
                        generate warnings if the Cursor files doesn't exists
125
430
 
126
 
  @todo
 
431
  TODO:
127
432
    When logging to the binary log, we should log
128
433
    tmp_tables and transactional tables as separate statements if we
129
434
    are in a transaction;  This is needed to get these tables into the
139
444
   -1   Thread was killed
140
445
*/
141
446
 
142
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                   bool drop_temporary)
 
447
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
448
                         bool drop_temporary, bool dont_log_query)
144
449
{
145
450
  TableList *table;
 
451
  char path[FN_REFLEN];
 
452
  uint32_t path_length= 0;
146
453
  String wrong_tables;
147
454
  int error= 0;
148
455
  bool foreign_key_error= false;
149
456
 
150
 
  do
151
 
  {
152
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
153
 
 
154
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
 
    {
156
 
      return 1;
157
 
    }
158
 
 
159
 
    /* Don't give warnings for not found errors, as we already generate notes */
160
 
    session->no_warnings_for_error= 1;
161
 
 
162
 
    for (table= tables; table; table= table->next_local)
163
 
    {
164
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
165
 
 
166
 
      error= session->drop_temporary_table(tmp_identifier);
167
 
 
168
 
      switch (error) {
169
 
      case  0:
170
 
        // removed temporary table
171
 
        continue;
172
 
      case -1:
 
457
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
 
458
 
 
459
  /*
 
460
    If we have the table in the definition cache, we don't have to check the
 
461
    .frm cursor to find if the table is a normal table (not view) and what
 
462
    engine to use.
 
463
  */
 
464
 
 
465
  for (table= tables; table; table= table->next_local)
 
466
  {
 
467
    TableShare *share;
 
468
    table->db_type= NULL;
 
469
    if ((share= TableShare::getShare(table->db, table->table_name)))
 
470
      table->db_type= share->db_type();
 
471
  }
 
472
 
 
473
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
 
474
  {
 
475
    pthread_mutex_unlock(&LOCK_open);
 
476
    return 1;
 
477
  }
 
478
 
 
479
  /* Don't give warnings for not found errors, as we already generate notes */
 
480
  session->no_warnings_for_error= 1;
 
481
 
 
482
  for (table= tables; table; table= table->next_local)
 
483
  {
 
484
    char *db=table->db;
 
485
    plugin::StorageEngine *table_type;
 
486
 
 
487
    error= session->drop_temporary_table(table);
 
488
 
 
489
    switch (error) {
 
490
    case  0:
 
491
      // removed temporary table
 
492
      continue;
 
493
    case -1:
 
494
      error= 1;
 
495
      goto err_with_placeholders;
 
496
    default:
 
497
      // temporary table not found
 
498
      error= 0;
 
499
    }
 
500
 
 
501
    table_type= table->db_type;
 
502
    if (!drop_temporary)
 
503
    {
 
504
      Table *locked_table;
 
505
      abort_locked_tables(session, db, table->table_name);
 
506
      remove_table_from_cache(session, db, table->table_name,
 
507
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
508
                              RTFC_CHECK_KILLED_FLAG);
 
509
      /*
 
510
        If the table was used in lock tables, remember it so that
 
511
        unlock_table_names can free it
 
512
      */
 
513
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
 
514
        table->table= locked_table;
 
515
 
 
516
      if (session->killed)
 
517
      {
 
518
        error= -1;
 
519
        goto err_with_placeholders;
 
520
      }
 
521
      /* remove .frm cursor and engine files */
 
522
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
 
523
    }
 
524
 
 
525
    if (drop_temporary ||
 
526
        ((table_type == NULL
 
527
          && (plugin::StorageEngine::getTableDefinition(*session, 
 
528
                                                        path, 
 
529
                                                        db, 
 
530
                                                        table->table_name, 
 
531
                                                        table->internal_tmp_table) != EEXIST))))
 
532
    {
 
533
      // Table was not found on disk and table can't be created from engine
 
534
      if (if_exists)
 
535
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
536
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
537
                            table->table_name);
 
538
      else
173
539
        error= 1;
174
 
        break;
175
 
      default:
176
 
        // temporary table not found
177
 
        error= 0;
178
 
      }
179
 
 
180
 
      if (drop_temporary == false)
181
 
      {
182
 
        Table *locked_table;
183
 
        abort_locked_tables(session, tmp_identifier);
184
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
185
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
186
 
                                              RTFC_CHECK_KILLED_FLAG);
187
 
        /*
188
 
          If the table was used in lock tables, remember it so that
189
 
          unlock_table_names can free it
190
 
        */
191
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
192
 
          table->table= locked_table;
193
 
 
194
 
        if (session->getKilled())
195
 
        {
196
 
          error= -1;
197
 
          break;
198
 
        }
199
 
      }
200
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
201
 
 
202
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
203
 
      {
204
 
        // Table was not found on disk and table can't be created from engine
205
 
        if (if_exists)
206
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
 
                              table->getTableName());
209
 
        else
210
 
        {
211
 
          error= 1;
212
 
        }
213
 
      }
214
 
      else
215
 
      {
216
 
        drizzled::error_t local_error;
217
 
 
218
 
        /* Generate transaction event ONLY when we successfully drop */ 
219
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
220
 
        {
221
 
          TransactionServices &transaction_services= TransactionServices::singleton();
222
 
          transaction_services.dropTable(*session, identifier, if_exists);
223
 
        }
224
 
        else
225
 
        {
226
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
227
 
          {
228
 
            error= 0;
229
 
            session->clear_error();
230
 
          }
231
 
 
232
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
233
 
          {
234
 
            /* the table is referenced by a foreign key constraint */
235
 
            foreign_key_error= true;
236
 
          }
237
 
          error= local_error;
238
 
        }
239
 
      }
240
 
 
241
 
      if (error)
242
 
      {
243
 
        if (wrong_tables.length())
244
 
          wrong_tables.append(',');
245
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
246
 
      }
247
 
    }
248
 
 
249
 
    tables->unlock_table_names();
250
 
 
251
 
  } while (0);
252
 
 
 
540
    }
 
541
    else
 
542
    {
 
543
      error= plugin::StorageEngine::dropTable(*session, path, db,
 
544
                                                table->table_name,
 
545
                                                ! dont_log_query);
 
546
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
547
      {
 
548
        error= 0;
 
549
        session->clear_error();
 
550
      }
 
551
 
 
552
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
553
      {
 
554
        /* the table is referenced by a foreign key constraint */
 
555
        foreign_key_error= true;
 
556
      }
 
557
    }
 
558
 
 
559
    if (error == 0 || (if_exists && foreign_key_error == false))
 
560
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
561
 
 
562
    if (error)
 
563
    {
 
564
      if (wrong_tables.length())
 
565
        wrong_tables.append(',');
 
566
      wrong_tables.append(String(table->table_name,system_charset_info));
 
567
    }
 
568
  }
 
569
  /*
 
570
    It's safe to unlock LOCK_open: we have an exclusive lock
 
571
    on the table name.
 
572
  */
 
573
  pthread_mutex_unlock(&LOCK_open);
 
574
  error= 0;
253
575
  if (wrong_tables.length())
254
576
  {
255
 
    if (not foreign_key_error)
256
 
    {
 
577
    if (!foreign_key_error)
257
578
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
579
                      wrong_tables.c_ptr());
259
 
    }
260
580
    else
261
581
    {
262
582
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
264
584
    error= 1;
265
585
  }
266
586
 
 
587
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
 
588
err_with_placeholders:
 
589
  unlock_table_names(tables, NULL);
 
590
  pthread_mutex_unlock(&LOCK_open);
267
591
  session->no_warnings_for_error= 0;
268
592
 
269
 
  return error;
 
593
  return(error);
 
594
}
 
595
 
 
596
 
 
597
/*
 
598
  Quickly remove a table.
 
599
 
 
600
  SYNOPSIS
 
601
    quick_rm_table()
 
602
      base                      The plugin::StorageEngine handle.
 
603
      db                        The database name.
 
604
      table_name                The table name.
 
605
      is_tmp                    If the table is temp.
 
606
 
 
607
  RETURN
 
608
    0           OK
 
609
    != 0        Error
 
610
*/
 
611
 
 
612
bool quick_rm_table(Session& session, const char *db,
 
613
                    const char *table_name, bool is_tmp)
 
614
{
 
615
  char path[FN_REFLEN];
 
616
  bool error= 0;
 
617
 
 
618
  build_table_filename(path, sizeof(path), db, table_name, is_tmp);
 
619
 
 
620
  return (plugin::StorageEngine::dropTable(session, path, db,
 
621
                                           table_name, 0)
 
622
          || error);
270
623
}
271
624
 
272
625
/*
282
635
  PRIMARY keys are prioritized.
283
636
*/
284
637
 
285
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
638
static int sort_keys(KEY *a, KEY *b)
286
639
{
287
640
  ulong a_flags= a->flags, b_flags= b->flags;
288
641
 
334
687
    1             Error
335
688
*/
336
689
 
337
 
class typelib_set_member
338
 
{
339
 
public:
340
 
  string s;
341
 
  const CHARSET_INFO * const cs;
342
 
 
343
 
  typelib_set_member(const char* value, unsigned int length,
344
 
                     const CHARSET_INFO * const charset)
345
 
    : s(value, length),
346
 
      cs(charset)
347
 
  {}
348
 
};
349
 
 
350
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
351
 
{
352
 
  return (my_strnncoll(a.cs,
353
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
354
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
355
 
}
356
 
 
357
 
 
358
 
namespace
359
 
{
360
 
class typelib_set_member_hasher
361
 
{
362
 
  boost::hash<string> hasher;
363
 
public:
364
 
  std::size_t operator()(const typelib_set_member& t) const
365
 
  {
366
 
    return hasher(t.s);
367
 
  }
368
 
};
369
 
}
370
 
 
371
690
static bool check_duplicates_in_interval(const char *set_or_name,
372
691
                                         const char *name, TYPELIB *typelib,
373
692
                                         const CHARSET_INFO * const cs,
378
697
  unsigned int *cur_length= typelib->type_lengths;
379
698
  *dup_val_count= 0;
380
699
 
381
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
382
 
 
383
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
700
  for ( ; tmp.count > 1; cur_value++, cur_length++)
384
701
  {
385
702
    tmp.type_names++;
386
703
    tmp.type_lengths++;
387
704
    tmp.count--;
388
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
705
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
389
706
    {
390
707
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
708
               name,*cur_value,set_or_name);
392
709
      return 1;
393
710
    }
394
 
    else
395
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
396
711
  }
397
712
  return 0;
398
713
}
441
756
    sql_field     field to prepare for packing
442
757
    blob_columns  count for BLOBs
443
758
    timestamps    count for timestamps
 
759
    table_flags   table flags
444
760
 
445
761
  DESCRIPTION
446
762
    This function prepares a CreateField instance.
452
768
*/
453
769
int prepare_create_field(CreateField *sql_field,
454
770
                         uint32_t *blob_columns,
455
 
                         int *timestamps,
456
 
                         int *timestamps_with_niladic)
 
771
                         int *timestamps, int *timestamps_with_niladic,
 
772
                         int64_t )
457
773
{
458
774
  unsigned int dup_val_count;
459
775
 
465
781
 
466
782
  switch (sql_field->sql_type) {
467
783
  case DRIZZLE_TYPE_BLOB:
 
784
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
468
785
    sql_field->length= 8; // Unireg field length
469
786
    (*blob_columns)++;
470
787
    break;
471
 
 
 
788
  case DRIZZLE_TYPE_VARCHAR:
 
789
    sql_field->pack_flag=0;
 
790
    break;
472
791
  case DRIZZLE_TYPE_ENUM:
473
 
    {
474
 
      if (check_duplicates_in_interval("ENUM",
475
 
                                       sql_field->field_name,
476
 
                                       sql_field->interval,
477
 
                                       sql_field->charset,
478
 
                                       &dup_val_count))
479
 
      {
480
 
        return 1;
481
 
      }
482
 
    }
483
 
    break;
484
 
 
485
 
  case DRIZZLE_TYPE_MICROTIME:
 
792
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
 
793
    if (check_duplicates_in_interval("ENUM",
 
794
                                     sql_field->field_name,
 
795
                                     sql_field->interval,
 
796
                                     sql_field->charset,
 
797
                                     &dup_val_count))
 
798
      return 1;
 
799
    break;
 
800
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
801
  case DRIZZLE_TYPE_DATETIME:
 
802
  case DRIZZLE_TYPE_NULL:
 
803
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
 
804
    break;
 
805
  case DRIZZLE_TYPE_DECIMAL:
 
806
    sql_field->pack_flag= 0;
 
807
    break;
486
808
  case DRIZZLE_TYPE_TIMESTAMP:
487
809
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
810
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
493
815
        (*timestamps_with_niladic)++;
494
816
      }
495
817
      else
496
 
      {
497
818
        sql_field->unireg_check= Field::NONE;
498
 
      }
499
819
    }
500
820
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
821
      (*timestamps_with_niladic)++;
503
 
    }
504
822
 
505
823
    (*timestamps)++;
506
 
 
507
 
    break;
508
 
 
509
 
  case DRIZZLE_TYPE_BOOLEAN:
510
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
511
 
  case DRIZZLE_TYPE_DATETIME:
512
 
  case DRIZZLE_TYPE_DECIMAL:
513
 
  case DRIZZLE_TYPE_DOUBLE:
514
 
  case DRIZZLE_TYPE_LONG:
515
 
  case DRIZZLE_TYPE_LONGLONG:
516
 
  case DRIZZLE_TYPE_NULL:
517
 
  case DRIZZLE_TYPE_TIME:
518
 
  case DRIZZLE_TYPE_UUID:
519
 
  case DRIZZLE_TYPE_VARCHAR:
 
824
    /* fall-through */
 
825
  default:
 
826
    sql_field->pack_flag=(0 |
 
827
                          f_settype((uint32_t) sql_field->sql_type));
520
828
    break;
521
829
  }
522
 
 
523
830
  return 0;
524
831
}
525
832
 
526
 
static int prepare_create_table(Session *session,
527
 
                                HA_CREATE_INFO *create_info,
528
 
                                message::Table &create_proto,
529
 
                                AlterInfo *alter_info,
530
 
                                bool tmp_table,
531
 
                                uint32_t *db_options,
532
 
                                KeyInfo **key_info_buffer,
533
 
                                uint32_t *key_count,
534
 
                                int select_field_count)
 
833
int mysql_prepare_create_table(Session *session,
 
834
                               HA_CREATE_INFO *create_info,
 
835
                               message::Table *create_proto,
 
836
                               AlterInfo *alter_info,
 
837
                               bool tmp_table,
 
838
                               uint32_t *db_options,
 
839
                               Cursor *cursor,
 
840
                               KEY **key_info_buffer,
 
841
                               uint32_t *key_count,
 
842
                               int select_field_count)
535
843
{
536
844
  const char    *key_name;
537
845
  CreateField   *sql_field,*dup_field;
538
846
  uint          field,null_fields,blob_columns,max_key_length;
539
847
  ulong         record_offset= 0;
540
 
  KeyInfo               *key_info;
541
 
  KeyPartInfo *key_part_info;
 
848
  KEY           *key_info;
 
849
  KEY_PART_INFO *key_part_info;
542
850
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
851
  int           field_no,dup_no;
544
852
  int           select_field_pos,auto_increment=0;
545
853
  List_iterator<CreateField> it(alter_info->create_list);
546
854
  List_iterator<CreateField> it2(alter_info->create_list);
547
855
  uint32_t total_uneven_bit_length= 0;
548
856
 
549
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
550
 
 
551
857
  select_field_pos= alter_info->create_list.elements - select_field_count;
552
858
  null_fields=blob_columns=0;
553
 
  max_key_length= engine->max_key_length();
 
859
  max_key_length= cursor->max_key_length();
554
860
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
861
  for (field_no=0; (sql_field=it++) ; field_no++)
556
862
  {
557
863
    const CHARSET_INFO *save_cs;
558
864
 
562
868
      executing a prepared statement for the second time.
563
869
    */
564
870
    sql_field->length= sql_field->char_length;
565
 
 
566
871
    if (!sql_field->charset)
567
872
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
873
    /*
570
874
      table_charset is set in ALTER Table if we want change character set
571
875
      for all varchar/char columns.
618
922
 
619
923
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
924
    {
621
 
      size_t dummy;
 
925
      uint32_t dummy;
622
926
      const CHARSET_INFO * const cs= sql_field->charset;
623
927
      TYPELIB *interval= sql_field->interval;
624
928
 
651
955
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
956
                                       cs, &dummy))
653
957
          {
654
 
            size_t cnv_errs;
 
958
            uint32_t cnv_errs;
655
959
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
656
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
960
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
 
961
                                                  conv.length());
657
962
            interval->type_lengths[i]= conv.length();
658
963
          }
659
964
 
693
998
            }
694
999
          }
695
1000
        }
696
 
        uint32_t new_dummy;
697
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
1001
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
698
1002
        sql_field->length= field_length;
699
1003
      }
700
1004
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
758
1062
        }
759
1063
      }
760
1064
    }
761
 
 
762
 
    /** @todo Get rid of this MyISAM-specific crap. */
763
 
    if (not create_proto.engine().name().compare("MyISAM") &&
764
 
        ((sql_field->flags & BLOB_FLAG) ||
765
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
766
 
    {
 
1065
    /* Don't pack rows in old tables if the user has requested this */
 
1066
    if ((sql_field->flags & BLOB_FLAG) ||
 
1067
        (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
767
1068
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
1069
    it2.rewind();
771
1070
  }
772
1071
 
780
1079
    assert(sql_field->charset != 0);
781
1080
 
782
1081
    if (prepare_create_field(sql_field, &blob_columns,
783
 
                             &timestamps, &timestamps_with_niladic))
 
1082
                             &timestamps, &timestamps_with_niladic,
 
1083
                             cursor->ha_table_flags()))
784
1084
      return(true);
785
1085
    sql_field->offset= record_offset;
786
1086
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
798
1098
    return(true);
799
1099
  }
800
1100
  if (auto_increment &&
801
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
1101
      (cursor->ha_table_flags() & HA_NO_AUTO_INCREMENT))
802
1102
  {
803
1103
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
804
1104
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
805
1105
    return(true);
806
1106
  }
807
1107
 
808
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
1108
  if (blob_columns && (cursor->ha_table_flags() & HA_NO_BLOBS))
809
1109
  {
810
1110
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
811
1111
               MYF(0));
833
1133
      fk_key_count++;
834
1134
      if (((Foreign_key *)key)->validate(alter_info->create_list))
835
1135
        return true;
836
 
 
837
1136
      Foreign_key *fk_key= (Foreign_key*) key;
838
 
 
839
 
      add_foreign_key_to_table_message(&create_proto,
840
 
                                       fk_key->name.str,
841
 
                                       fk_key->columns,
842
 
                                       fk_key->ref_table,
843
 
                                       fk_key->ref_columns,
844
 
                                       fk_key->delete_opt,
845
 
                                       fk_key->update_opt,
846
 
                                       fk_key->match_opt);
847
 
 
848
1137
      if (fk_key->ref_columns.elements &&
849
1138
          fk_key->ref_columns.elements != fk_key->columns.elements)
850
1139
      {
857
1146
      continue;
858
1147
    }
859
1148
    (*key_count)++;
860
 
    tmp= engine->max_key_parts();
 
1149
    tmp=cursor->max_key_parts();
861
1150
    if (key->columns.elements > tmp)
862
1151
    {
863
1152
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
879
1168
             key2->name.str != ignore_key &&
880
1169
             !foreign_key_prefix(key, key2)))
881
1170
        {
882
 
          /* @todo issue warning message */
 
1171
          /* TODO: issue warning message */
883
1172
          /* mark that the generated key should be ignored */
884
1173
          if (!key2->generated ||
885
1174
              (key->generated && key->columns.elements <
906
1195
      return(true);
907
1196
    }
908
1197
  }
909
 
  tmp= engine->max_keys();
 
1198
  tmp=cursor->max_keys();
910
1199
  if (*key_count > tmp)
911
1200
  {
912
1201
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
913
1202
    return(true);
914
1203
  }
915
1204
 
916
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
917
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
1205
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
1206
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
918
1207
  if (!*key_info_buffer || ! key_part_info)
919
1208
    return(true);                               // Out of memory
920
1209
 
954
1243
    key_info->usable_key_parts= key_number;
955
1244
    key_info->algorithm= key->key_create_info.algorithm;
956
1245
 
 
1246
    /* Take block size from key part or table part */
 
1247
    /*
 
1248
      TODO: Add warning if block size changes. We can't do it here, as
 
1249
      this may depend on the size of the key
 
1250
    */
 
1251
    key_info->block_size= (key->key_create_info.block_size ?
 
1252
                           key->key_create_info.block_size :
 
1253
                           create_proto->options().key_block_size());
 
1254
 
 
1255
    if (key_info->block_size)
 
1256
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
1257
 
957
1258
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
958
1259
                                           key->key_create_info.comment.str,
959
1260
                                           key->key_create_info.comment.str +
990
1291
             my_strcasecmp(system_charset_info,
991
1292
                           column->field_name.str,
992
1293
                           sql_field->field_name))
993
 
      {
994
1294
        field++;
995
 
      }
996
 
 
997
1295
      if (!sql_field)
998
1296
      {
999
1297
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
1298
        return(true);
1001
1299
      }
1002
 
 
1003
1300
      while ((dup_column= cols2++) != column)
1004
1301
      {
1005
1302
        if (!my_strcasecmp(system_charset_info,
1006
 
                           column->field_name.str, dup_column->field_name.str))
 
1303
                           column->field_name.str, dup_column->field_name.str))
1007
1304
        {
1008
1305
          my_printf_error(ER_DUP_FIELDNAME,
1009
1306
                          ER(ER_DUP_FIELDNAME),MYF(0),
1013
1310
      }
1014
1311
      cols2.rewind();
1015
1312
 
1016
 
      if (create_proto.field_size() > 0)
1017
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
 
1313
      if (create_proto->field_size() > 0)
 
1314
        protofield= create_proto->mutable_field(proto_field_nr - 1);
1018
1315
 
1019
1316
      {
1020
1317
        column->length*= sql_field->charset->mbmaxlen;
1021
1318
 
1022
1319
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1023
1320
        {
1024
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
 
1321
          if (! (cursor->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1025
1322
          {
1026
1323
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1027
1324
            return true;
1032
1329
            return true;
1033
1330
          }
1034
1331
        }
1035
 
 
1036
1332
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
1333
        {
1038
1334
          if (key->type == Key::PRIMARY)
1045
1341
            {
1046
1342
              message::Table::Field::FieldConstraints *constraints;
1047
1343
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
 
1344
              constraints->set_is_nullable(false);
1049
1345
            }
1050
1346
 
1051
1347
          }
1052
1348
          else
1053
1349
          {
1054
1350
            key_info->flags|= HA_NULL_PART_KEY;
1055
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
1351
            if (! (cursor->ha_table_flags() & HA_NULL_IN_KEY))
1056
1352
            {
1057
1353
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1058
1354
              return true;
1059
1355
            }
1060
1356
          }
1061
1357
        }
1062
 
 
1063
1358
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
1359
        {
1065
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
 
1360
          if (column_nr == 0 || (cursor->ha_table_flags() & HA_AUTO_PART_KEY))
1066
1361
            auto_increment--;                   // Field is used
1067
1362
        }
1068
1363
      }
1069
1364
 
1070
1365
      key_part_info->fieldnr= field;
1071
1366
      key_part_info->offset=  (uint16_t) sql_field->offset;
1072
 
      key_part_info->key_type= 0;
 
1367
      key_part_info->key_type=sql_field->pack_flag;
1073
1368
      length= sql_field->key_length;
1074
1369
 
1075
1370
      if (column->length)
1077
1372
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1078
1373
        {
1079
1374
          if ((length=column->length) > max_key_length ||
1080
 
              length > engine->max_key_part_length())
 
1375
              length > cursor->max_key_part_length())
1081
1376
          {
1082
 
            length= min(max_key_length, engine->max_key_part_length());
 
1377
            length= min(max_key_length, cursor->max_key_part_length());
1083
1378
            if (key->type == Key::MULTIPLE)
1084
1379
            {
1085
1380
              /* not a critical problem */
1104
1399
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1105
1400
          return(true);
1106
1401
        }
1107
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1108
 
        {
 
1402
        else if (!(cursor->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1109
1403
          length=column->length;
1110
 
        }
1111
1404
      }
1112
1405
      else if (length == 0)
1113
1406
      {
1114
1407
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1115
1408
          return(true);
1116
1409
      }
1117
 
      if (length > engine->max_key_part_length())
 
1410
      if (length > cursor->max_key_part_length())
1118
1411
      {
1119
 
        length= engine->max_key_part_length();
 
1412
        length= cursor->max_key_part_length();
1120
1413
        if (key->type == Key::MULTIPLE)
1121
1414
        {
1122
1415
          /* not a critical problem */
1137
1430
      key_part_info->length=(uint16_t) length;
1138
1431
      /* Use packed keys for long strings on the first column */
1139
1432
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1140
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1141
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1142
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
1433
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
1434
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
 
1435
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1143
1436
      {
1144
1437
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1145
1438
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1146
 
        {
1147
1439
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1148
 
        }
1149
1440
        else
1150
 
        {
1151
1441
          key_info->flags|= HA_PACK_KEY;
1152
 
        }
1153
1442
      }
1154
1443
      /* Check if the key segment is partial, set the key flag accordingly */
1155
1444
      if (length != sql_field->key_length)
1184
1473
        key_info->name=(char*) key_name;
1185
1474
      }
1186
1475
    }
1187
 
 
1188
1476
    if (!key_info->name || check_column_name(key_info->name))
1189
1477
    {
1190
1478
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1479
      return(true);
1192
1480
    }
1193
 
 
1194
1481
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1482
      unique_key=1;
1197
 
    }
1198
 
 
1199
1483
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1484
    if (key_length > max_key_length)
1202
1485
    {
1203
1486
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1487
      return(true);
1205
1488
    }
1206
 
 
1207
1489
    key_info++;
1208
1490
  }
1209
 
 
1210
1491
  if (!unique_key && !primary_key &&
1211
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
1492
      (cursor->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1212
1493
  {
1213
1494
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1495
    return(true);
1215
1496
  }
1216
 
 
1217
1497
  if (auto_increment > 0)
1218
1498
  {
1219
1499
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1220
1500
    return(true);
1221
1501
  }
1222
1502
  /* Sort keys in optimized order */
1223
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1224
 
                     (qsort_cmp) sort_keys);
 
1503
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
 
1504
           (qsort_cmp) sort_keys);
1225
1505
 
1226
1506
  /* Check fields. */
1227
1507
  it.rewind();
1294
1574
  return 0;
1295
1575
}
1296
1576
 
1297
 
static bool locked_create_event(Session *session,
1298
 
                                const identifier::Table &identifier,
1299
 
                                HA_CREATE_INFO *create_info,
1300
 
                                message::Table &table_proto,
1301
 
                                AlterInfo *alter_info,
1302
 
                                bool is_if_not_exists,
1303
 
                                bool internal_tmp_table,
1304
 
                                uint db_options,
1305
 
                                uint key_count,
1306
 
                                KeyInfo *key_info_buffer)
1307
 
{
1308
 
  bool error= true;
1309
 
 
1310
 
  {
1311
 
 
1312
 
    /*
1313
 
      @note if we are building a temp table we need to check to see if a temp table
1314
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1315
 
      to create a table under a temporary table.
1316
 
    */
1317
 
    bool exists= 
1318
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1319
 
                                            identifier.getType() != message::Table::STANDARD );
1320
 
 
1321
 
    if (exists)
1322
 
    {
1323
 
      if (is_if_not_exists)
1324
 
      {
1325
 
        error= false;
1326
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1327
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1328
 
                            identifier.getTableName().c_str());
1329
 
        create_info->table_existed= 1;          // Mark that table existed
1330
 
        return error;
1331
 
      }
1332
 
 
1333
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1334
 
 
1335
 
      return error;
1336
 
    }
1337
 
 
1338
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1339
 
    {
1340
 
      /*
1341
 
        We don't assert here, but check the result, because the table could be
1342
 
        in the table definition cache and in the same time the .frm could be
1343
 
        missing from the disk, in case of manual intervention which deletes
1344
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1345
 
        Then she could create the table. This case is pretty obscure and
1346
 
        therefore we don't introduce a new error message only for it.
1347
 
      */
1348
 
      /*
1349
 
        @todo improve this error condition.
1350
 
      */
1351
 
      if (definition::Cache::singleton().find(identifier.getKey()))
1352
 
      {
1353
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
 
 
1355
 
        return error;
1356
 
      }
1357
 
    }
1358
 
  }
1359
 
 
1360
 
  session->set_proc_info("creating table");
1361
 
  create_info->table_existed= 0;                // Mark that table is created
1362
 
 
1363
 
  create_info->table_options= db_options;
1364
 
 
1365
 
  if (not rea_create_table(session, identifier,
1366
 
                           table_proto,
1367
 
                           create_info, alter_info->create_list,
1368
 
                           key_count, key_info_buffer))
1369
 
  {
1370
 
    return error;
1371
 
  }
1372
 
 
1373
 
  if (identifier.getType() == message::Table::TEMPORARY)
1374
 
  {
1375
 
    /* Open table and put in temporary table list */
1376
 
    if (not (session->open_temporary_table(identifier)))
1377
 
    {
1378
 
      (void) session->rm_temporary_table(identifier);
1379
 
      return error;
1380
 
    }
1381
 
  }
1382
 
 
1383
 
  /* 
1384
 
    We keep this behind the lock to make sure ordering is correct for a table.
1385
 
    This is a very unlikely problem where before we would write out to the
1386
 
    trans log, someone would do a delete/create operation.
1387
 
  */
1388
 
 
1389
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1390
 
  {
1391
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1392
 
    transaction_services.createTable(*session, table_proto);
1393
 
  }
1394
 
 
1395
 
  return false;
1396
 
}
1397
 
 
1398
1577
 
1399
1578
/*
1400
1579
  Ignore the name of this function... it locks :(
1402
1581
  Create a table
1403
1582
 
1404
1583
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1584
    mysql_create_table_no_lock()
1406
1585
    session                     Thread object
1407
1586
    db                  Database
1408
1587
    table_name          Table name
1418
1597
 
1419
1598
    Note that this function assumes that caller already have taken
1420
1599
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1600
    that concurrent operations won't intervene. mysql_create_table()
1422
1601
    is a wrapper that can be used for this.
1423
1602
 
1424
1603
  RETURN VALUES
1426
1605
    true  error
1427
1606
*/
1428
1607
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1608
bool mysql_create_table_no_lock(Session *session,
 
1609
                                const char *db, const char *table_name,
1431
1610
                                HA_CREATE_INFO *create_info,
1432
 
                                message::Table &table_proto,
 
1611
                                message::Table *table_proto,
1433
1612
                                AlterInfo *alter_info,
1434
1613
                                bool internal_tmp_table,
1435
 
                                uint32_t select_field_count,
1436
 
                                bool is_if_not_exists)
 
1614
                                uint32_t select_field_count)
1437
1615
{
 
1616
  char          path[FN_REFLEN];
 
1617
  uint32_t          path_length;
1438
1618
  uint          db_options, key_count;
1439
 
  KeyInfo               *key_info_buffer;
 
1619
  KEY           *key_info_buffer;
 
1620
  Cursor        *cursor;
1440
1621
  bool          error= true;
 
1622
  TableShare share;
1441
1623
 
1442
1624
  /* Check for duplicate fields and check type of table to create */
1443
 
  if (not alter_info->create_list.elements)
 
1625
  if (!alter_info->create_list.elements)
1444
1626
  {
1445
1627
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1446
1628
               MYF(0));
1447
1629
    return true;
1448
1630
  }
1449
 
  assert(identifier.getTableName() == table_proto.name());
 
1631
  assert(strcmp(table_name,table_proto->name().c_str())==0);
 
1632
  if (check_engine(session, table_name, create_info))
 
1633
    return true;
1450
1634
  db_options= create_info->table_options;
1451
 
 
1452
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1453
 
 
1454
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1455
 
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1456
 
                               internal_tmp_table,
1457
 
                               &db_options,
1458
 
                               &key_info_buffer, &key_count,
1459
 
                               select_field_count))
1460
 
  {
1461
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
 
    error= locked_create_event(session,
1463
 
                               identifier,
1464
 
                               create_info,
1465
 
                               table_proto,
1466
 
                               alter_info,
1467
 
                               is_if_not_exists,
1468
 
                               internal_tmp_table,
1469
 
                               db_options, key_count,
1470
 
                               key_info_buffer);
1471
 
  }
1472
 
 
 
1635
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
1636
    db_options|=HA_OPTION_PACK_RECORD;
 
1637
  if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
 
1638
  {
 
1639
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
 
1640
    return true;
 
1641
  }
 
1642
 
 
1643
  set_table_default_charset(create_info, (char*) db);
 
1644
 
 
1645
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1646
                                 internal_tmp_table,
 
1647
                                 &db_options, cursor,
 
1648
                                 &key_info_buffer, &key_count,
 
1649
                                 select_field_count))
 
1650
    goto err;
 
1651
 
 
1652
      /* Check if table exists */
 
1653
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1654
  {
 
1655
    path_length= build_tmptable_filename(session, path, sizeof(path));
 
1656
  }
 
1657
  else
 
1658
  {
 
1659
 #ifdef FN_DEVCHAR
 
1660
    /* check if the table name contains FN_DEVCHAR when defined */
 
1661
    if (strchr(table_name, FN_DEVCHAR))
 
1662
    {
 
1663
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
 
1664
      return true;
 
1665
    }
 
1666
#endif
 
1667
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
 
1668
  }
 
1669
 
 
1670
  /* Check if table already exists */
 
1671
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1672
      session->find_temporary_table(db, table_name))
 
1673
  {
 
1674
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1675
    {
 
1676
      create_info->table_existed= 1;            // Mark that table existed
 
1677
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1678
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1679
                          table_name);
 
1680
      error= 0;
 
1681
      goto err;
 
1682
    }
 
1683
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1684
    goto err;
 
1685
  }
 
1686
 
 
1687
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1688
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1689
  {
 
1690
    if (plugin::StorageEngine::getTableDefinition(*session, path, db, table_name, internal_tmp_table)==EEXIST)
 
1691
    {
 
1692
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1693
      {
 
1694
        error= false;
 
1695
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1696
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1697
                            table_name);
 
1698
        create_info->table_existed= 1;          // Mark that table existed
 
1699
      }
 
1700
      else 
 
1701
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1702
 
 
1703
      goto unlock_and_end;
 
1704
    }
 
1705
    /*
 
1706
      We don't assert here, but check the result, because the table could be
 
1707
      in the table definition cache and in the same time the .frm could be
 
1708
      missing from the disk, in case of manual intervention which deletes
 
1709
      the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
 
1710
      Then she could create the table. This case is pretty obscure and
 
1711
      therefore we don't introduce a new error message only for it.
 
1712
    */
 
1713
    if (TableShare::getShare(db, table_name))
 
1714
    {
 
1715
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1716
      goto unlock_and_end;
 
1717
    }
 
1718
  }
 
1719
 
 
1720
  /*
 
1721
    Check that table with given name does not already
 
1722
    exist in any storage engine. In such a case it should
 
1723
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
1724
    unless user specified CREATE TABLE IF EXISTS
 
1725
    The LOCK_open mutex has been locked to make sure no
 
1726
    one else is attempting to discover the table. Since
 
1727
    it's not on disk as a frm cursor, no one could be using it!
 
1728
  */
 
1729
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1730
  {
 
1731
    bool create_if_not_exists =
 
1732
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
1733
 
 
1734
    char table_path[FN_REFLEN];
 
1735
    uint32_t          table_path_length;
 
1736
 
 
1737
    table_path_length= build_table_filename(table_path, sizeof(table_path),
 
1738
                                            db, table_name, false);
 
1739
 
 
1740
    int retcode= plugin::StorageEngine::getTableDefinition(*session, table_path, db, table_name, false);
 
1741
    switch (retcode)
 
1742
    {
 
1743
      case ENOENT:
 
1744
        /* Normal case, no table exists. we can go and create it */
 
1745
        break;
 
1746
      case EEXIST:
 
1747
        if (create_if_not_exists)
 
1748
        {
 
1749
          error= false;
 
1750
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1751
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1752
                              table_name);
 
1753
          create_info->table_existed= 1;                // Mark that table existed
 
1754
          goto unlock_and_end;
 
1755
        }
 
1756
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1757
        goto unlock_and_end;
 
1758
      default:
 
1759
        my_error(retcode, MYF(0),table_name);
 
1760
        goto unlock_and_end;
 
1761
    }
 
1762
  }
 
1763
 
 
1764
  session->set_proc_info("creating table");
 
1765
  create_info->table_existed= 0;                // Mark that table is created
 
1766
 
 
1767
  create_info->table_options=db_options;
 
1768
 
 
1769
  if (rea_create_table(session, path, db, table_name,
 
1770
                       table_proto,
 
1771
                       create_info, alter_info->create_list,
 
1772
                       key_count, key_info_buffer))
 
1773
    goto unlock_and_end;
 
1774
 
 
1775
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1776
  {
 
1777
    /* Open table and put in temporary table list */
 
1778
    if (!(session->open_temporary_table(path, db, table_name)))
 
1779
    {
 
1780
      (void) session->rm_temporary_table(create_info->db_type, path);
 
1781
      goto unlock_and_end;
 
1782
    }
 
1783
  }
 
1784
 
 
1785
  /*
 
1786
    Don't write statement if:
 
1787
    - It is an internal temporary table,
 
1788
    - Row-based logging is used and it we are creating a temporary table, or
 
1789
    - The binary log is not open.
 
1790
    Otherwise, the statement shall be binlogged.
 
1791
   */
 
1792
  if (!internal_tmp_table &&
 
1793
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1794
    write_bin_log(session, session->query, session->query_length);
 
1795
  error= false;
 
1796
unlock_and_end:
 
1797
  pthread_mutex_unlock(&LOCK_open);
 
1798
 
 
1799
err:
1473
1800
  session->set_proc_info("After create");
1474
 
 
 
1801
  delete cursor;
1475
1802
  return(error);
1476
1803
}
1477
1804
 
1478
 
/**
1479
 
  @note the following two methods implement create [temporary] table.
 
1805
 
 
1806
/*
 
1807
  Database locking aware wrapper for mysql_create_table_no_lock(),
1480
1808
*/
1481
 
static bool drizzle_create_table(Session *session,
1482
 
                                 const identifier::Table &identifier,
1483
 
                                 HA_CREATE_INFO *create_info,
1484
 
                                 message::Table &table_proto,
1485
 
                                 AlterInfo *alter_info,
1486
 
                                 bool internal_tmp_table,
1487
 
                                 uint32_t select_field_count,
1488
 
                                 bool is_if_not_exists)
 
1809
 
 
1810
bool mysql_create_table(Session *session, const char *db, const char *table_name,
 
1811
                        HA_CREATE_INFO *create_info,
 
1812
                        message::Table *table_proto,
 
1813
                        AlterInfo *alter_info,
 
1814
                        bool internal_tmp_table,
 
1815
                        uint32_t select_field_count)
1489
1816
{
1490
1817
  Table *name_lock= NULL;
1491
1818
  bool result;
1492
1819
 
1493
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1494
 
  {
1495
 
    result= true;
1496
 
  }
1497
 
  else if (name_lock == NULL)
1498
 
  {
1499
 
    if (is_if_not_exists)
1500
 
    {
1501
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
 
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1503
 
                          identifier.getTableName().c_str());
1504
 
      create_info->table_existed= 1;
1505
 
      result= false;
1506
 
    }
1507
 
    else
1508
 
    {
1509
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1820
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1821
  {
 
1822
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
1823
    {
1510
1824
      result= true;
1511
 
    }
1512
 
  }
1513
 
  else
1514
 
  {
1515
 
    result= create_table_no_lock(session,
1516
 
                                       identifier,
1517
 
                                       create_info,
1518
 
                                       table_proto,
1519
 
                                       alter_info,
1520
 
                                       internal_tmp_table,
1521
 
                                       select_field_count,
1522
 
                                       is_if_not_exists);
1523
 
  }
1524
 
 
 
1825
      goto unlock;
 
1826
    }
 
1827
    if (name_lock == NULL)
 
1828
    {
 
1829
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1830
      {
 
1831
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1832
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1833
                            table_name);
 
1834
        create_info->table_existed= 1;
 
1835
        result= false;
 
1836
      }
 
1837
      else
 
1838
      {
 
1839
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1840
        result= true;
 
1841
      }
 
1842
      goto unlock;
 
1843
    }
 
1844
  }
 
1845
 
 
1846
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1847
                                     table_proto,
 
1848
                                     alter_info,
 
1849
                                     internal_tmp_table,
 
1850
                                     select_field_count);
 
1851
 
 
1852
unlock:
1525
1853
  if (name_lock)
1526
1854
  {
1527
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1855
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1528
1856
    session->unlink_open_table(name_lock);
 
1857
    pthread_mutex_unlock(&LOCK_open);
1529
1858
  }
1530
1859
 
1531
1860
  return(result);
1533
1862
 
1534
1863
 
1535
1864
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
1537
 
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
1540
 
                        HA_CREATE_INFO *create_info,
1541
 
                        message::Table &table_proto,
1542
 
                        AlterInfo *alter_info,
1543
 
                        bool internal_tmp_table,
1544
 
                        uint32_t select_field_count,
1545
 
                        bool is_if_not_exists)
1546
 
{
1547
 
  if (identifier.isTmp())
1548
 
  {
1549
 
    return create_table_no_lock(session,
1550
 
                                      identifier,
1551
 
                                      create_info,
1552
 
                                      table_proto,
1553
 
                                      alter_info,
1554
 
                                      internal_tmp_table,
1555
 
                                      select_field_count,
1556
 
                                      is_if_not_exists);
1557
 
  }
1558
 
 
1559
 
  return drizzle_create_table(session,
1560
 
                              identifier,
1561
 
                              create_info,
1562
 
                              table_proto,
1563
 
                              alter_info,
1564
 
                              internal_tmp_table,
1565
 
                              select_field_count,
1566
 
                              is_if_not_exists);
1567
 
}
1568
 
 
1569
 
 
1570
 
/*
1571
1865
** Give the key name after the first field with an optional '_#' after
1572
1866
**/
1573
1867
 
1574
1868
static bool
1575
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
1869
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1576
1870
{
1577
 
  for (KeyInfo *key=start ; key != end ; key++)
 
1871
  for (KEY *key=start ; key != end ; key++)
1578
1872
    if (!my_strcasecmp(system_charset_info,name,key->name))
1579
1873
      return 1;
1580
1874
  return 0;
1582
1876
 
1583
1877
 
1584
1878
static char *
1585
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
1879
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1586
1880
{
1587
1881
  char buff[MAX_FIELD_NAME],*buff_end;
1588
1882
 
1600
1894
  for (uint32_t i=2 ; i< 100; i++)
1601
1895
  {
1602
1896
    *buff_end= '_';
1603
 
    internal::int10_to_str(i, buff_end+1, 10);
 
1897
    int10_to_str(i, buff_end+1, 10);
1604
1898
    if (!check_if_keyname_exists(buff,start,end))
1605
 
      return memory::sql_strdup(buff);
 
1899
      return sql_strdup(buff);
1606
1900
  }
1607
1901
  return (char*) "not_specified";               // Should never happen
1608
1902
}
1616
1910
  Rename a table.
1617
1911
 
1618
1912
  SYNOPSIS
1619
 
    rename_table()
1620
 
      session
 
1913
    mysql_rename_table()
1621
1914
      base                      The plugin::StorageEngine handle.
1622
1915
      old_db                    The old database name.
1623
1916
      old_name                  The old table name.
1624
1917
      new_db                    The new database name.
1625
1918
      new_name                  The new table name.
 
1919
      flags                     flags for build_table_filename().
 
1920
                                FN_FROM_IS_TMP old_name is temporary.
 
1921
                                FN_TO_IS_TMP   new_name is temporary.
 
1922
                                NO_FRM_RENAME  Don't rename the FRM cursor
 
1923
                                but only the table in the storage engine.
1626
1924
 
1627
1925
  RETURN
1628
1926
    false   OK
1630
1928
*/
1631
1929
 
1632
1930
bool
1633
 
rename_table(Session &session,
1634
 
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1931
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
 
1932
                   const char *old_name, const char *new_db,
 
1933
                   const char *new_name, uint32_t flags)
1637
1934
{
 
1935
  Session *session= current_session;
 
1936
  char from[FN_REFLEN], to[FN_REFLEN];
 
1937
  char *from_base= from, *to_base= to;
1638
1938
  int error= 0;
1639
1939
 
1640
1940
  assert(base);
1641
1941
 
1642
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
 
1942
  build_table_filename(from, sizeof(from), old_db, old_name,
 
1943
                       flags & FN_FROM_IS_TMP);
 
1944
  build_table_filename(to, sizeof(to), new_db, new_name,
 
1945
                       flags & FN_TO_IS_TMP);
 
1946
 
 
1947
  if (!(error= base->renameTable(session, from_base, to_base)))
1643
1948
  {
1644
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1645
 
    return true;
 
1949
    if(!(flags & NO_FRM_RENAME)
 
1950
       && base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1951
       && rename_table_proto_file(from_base, to_base))
 
1952
    {
 
1953
      error= my_errno;
 
1954
      base->renameTable(session, to_base, from_base);
 
1955
    }
1646
1956
  }
1647
1957
 
1648
 
  error= base->renameTable(session, from, to);
1649
 
 
1650
1958
  if (error == HA_ERR_WRONG_COMMAND)
1651
 
  {
1652
1959
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1653
 
  }
1654
1960
  else if (error)
1655
 
  {
1656
 
    std::string from_path;
1657
 
    std::string to_path;
1658
 
 
1659
 
    from.getSQLPath(from_path);
1660
 
    to.getSQLPath(to_path);
1661
 
 
1662
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1663
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1664
 
 
1665
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1666
 
  }
1667
 
 
1668
 
  return error ? true : false; 
 
1961
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
1962
  return(error != 0);
1669
1963
}
1670
1964
 
1671
1965
 
1684
1978
   the table is closed.
1685
1979
 
1686
1980
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
1981
    Lock on LOCK_open
1688
1982
    Win32 clients must also have a WRITE LOCK on the table !
1689
1983
*/
1690
1984
 
1692
1986
                              enum ha_extra_function function)
1693
1987
{
1694
1988
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1989
  safe_mutex_assert_owner(&LOCK_open);
1696
1990
 
1697
1991
  table->cursor->extra(function);
1698
1992
  /* Mark all tables that are in use as 'old' */
1699
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1993
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1700
1994
 
1701
1995
  /* Wait until all there are no other threads that has this table open */
1702
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1703
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
1996
  remove_table_from_cache(session, table->s->db.str,
 
1997
                          table->s->table_name.str,
 
1998
                          RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1999
}
1705
2000
 
1706
2001
/*
1716
2011
    reopen the table.
1717
2012
 
1718
2013
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
2014
    Lock on LOCK_open
1720
2015
    Win32 clients must also have a WRITE LOCK on the table !
1721
2016
*/
1722
2017
 
1727
2022
  /* Close lock if this is not got with LOCK TABLES */
1728
2023
  if (lock)
1729
2024
  {
1730
 
    unlockTables(lock);
 
2025
    mysql_unlock_tables(this, lock);
1731
2026
    lock= NULL;                 // Start locked threads
1732
2027
  }
1733
2028
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
2029
  unlink_open_table(table);
1735
2030
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1737
 
  locking::broadcast_refresh();
 
2031
  /* When lock on LOCK_open is freed other threads can continue */
 
2032
  broadcast_refresh();
1738
2033
}
1739
2034
 
1740
2035
/*
1743
2038
    true  Message should be sent by caller
1744
2039
          (admin operation or network communication failed)
1745
2040
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
2041
static bool mysql_admin_table(Session* session, TableList* tables,
1747
2042
                              HA_CHECK_OPT* check_opt,
1748
2043
                              const char *operator_name,
1749
2044
                              thr_lock_type lock_type,
1750
2045
                              bool open_for_modify,
 
2046
                              bool no_warnings_for_error,
 
2047
                              uint32_t extra_open_options,
 
2048
                              int (*prepare_func)(Session *, TableList *,
 
2049
                                                  HA_CHECK_OPT *),
1751
2050
                              int (Cursor::*operator_func)(Session *,
1752
2051
                                                            HA_CHECK_OPT *))
1753
2052
{
1757
2056
  Item *item;
1758
2057
  LEX *lex= session->lex;
1759
2058
  int result_code= 0;
1760
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1761
2059
  const CHARSET_INFO * const cs= system_charset_info;
1762
2060
 
1763
2061
  if (! session->endActiveTransaction())
1772
2070
  item->maybe_null = 1;
1773
2071
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
2072
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
2073
  if (session->client->sendFields(&field_list))
1776
2074
    return true;
1777
2075
 
1778
2076
  for (table= tables; table; table= table->next_local)
1779
2077
  {
1780
2078
    char table_name[NAME_LEN*2+2];
 
2079
    char* db = table->db;
1781
2080
    bool fatal_error=0;
1782
2081
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
2082
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2083
    session->open_options|= extra_open_options;
1784
2084
    table->lock_type= lock_type;
1785
2085
    /* open only one table from local list of command */
1786
2086
    {
1793
2093
      /*
1794
2094
        Time zone tables and SP tables can be add to lex->query_tables list,
1795
2095
        so it have to be prepared.
1796
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
2096
        TODO: Investigate if we can put extra tables into argument instead of
 
2097
        using lex->query_tables
1797
2098
      */
1798
2099
      lex->query_tables= table;
1799
2100
      lex->query_tables_last= &table->next_global;
1800
2101
      lex->query_tables_own_last= 0;
1801
 
      session->no_warnings_for_error= 0;
 
2102
      session->no_warnings_for_error= no_warnings_for_error;
1802
2103
 
1803
2104
      session->openTablesLock(table);
1804
2105
      session->no_warnings_for_error= 0;
1805
2106
      table->next_global= save_next_global;
1806
2107
      table->next_local= save_next_local;
 
2108
      session->open_options&= ~extra_open_options;
 
2109
    }
 
2110
 
 
2111
    if (prepare_func)
 
2112
    {
 
2113
      switch ((*prepare_func)(session, table, check_opt)) {
 
2114
      case  1:           // error, message written to net
 
2115
        ha_autocommit_or_rollback(session, 1);
 
2116
        session->endTransaction(ROLLBACK);
 
2117
        session->close_thread_tables();
 
2118
        continue;
 
2119
      case -1:           // error, message could be written to net
 
2120
        goto err;
 
2121
      default:           // should be 0 otherwise
 
2122
        ;
 
2123
      }
1807
2124
    }
1808
2125
 
1809
2126
    /*
1827
2144
    {
1828
2145
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
2146
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
2147
      session->client->store(table_name);
 
2148
      session->client->store(operator_name);
 
2149
      session->client->store(STRING_WITH_LEN("error"));
1833
2150
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
2151
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
2152
      session->client->store(buff, length);
 
2153
      ha_autocommit_or_rollback(session, 0);
1837
2154
      session->endTransaction(COMMIT);
1838
2155
      session->close_thread_tables();
1839
2156
      lex->reset_query_tables_list(false);
1840
2157
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
2158
      if (session->client->flush())
1842
2159
        goto err;
1843
2160
      continue;
1844
2161
    }
1845
2162
 
1846
2163
    /* Close all instances of the table to allow repair to rename files */
1847
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
2164
    if (lock_type == TL_WRITE && table->table->s->version)
1848
2165
    {
1849
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1850
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1851
 
                                                  "Waiting to get writelock");
1852
 
      session->abortLock(table->table);
1853
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
2166
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2167
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
 
2168
                                              "Waiting to get writelock");
 
2169
      mysql_lock_abort(session,table->table);
 
2170
      remove_table_from_cache(session, table->table->s->db.str,
 
2171
                              table->table->s->table_name.str,
 
2172
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
2173
                              RTFC_CHECK_KILLED_FLAG);
1855
2174
      session->exit_cond(old_message);
1856
 
      if (session->getKilled())
 
2175
      if (session->killed)
1857
2176
        goto err;
1858
2177
      open_for_modify= 0;
1859
2178
    }
1860
2179
 
 
2180
    if (table->table->s->crashed && operator_func == &Cursor::ha_check)
 
2181
    {
 
2182
      session->client->store(table_name);
 
2183
      session->client->store(operator_name);
 
2184
      session->client->store(STRING_WITH_LEN("warning"));
 
2185
      session->client->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2186
      if (session->client->flush())
 
2187
        goto err;
 
2188
    }
 
2189
 
1861
2190
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
1862
2191
 
1863
2192
send_result:
1869
2198
      DRIZZLE_ERROR *err;
1870
2199
      while ((err= it++))
1871
2200
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
2201
        session->client->store(table_name);
 
2202
        session->client->store(operator_name);
 
2203
        session->client->store(warning_level_names[err->level].str,
1875
2204
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
2205
        session->client->store(err->msg);
 
2206
        if (session->client->flush())
1878
2207
          goto err;
1879
2208
      }
1880
2209
      drizzle_reset_errors(session, true);
1881
2210
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
2211
    session->client->store(table_name);
 
2212
    session->client->store(operator_name);
 
2213
 
 
2214
send_result_message:
1884
2215
 
1885
2216
    switch (result_code) {
1886
2217
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
2219
        char buf[ERRMSGSIZE+20];
1889
2220
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
2221
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
2222
        session->client->store(STRING_WITH_LEN("note"));
 
2223
        session->client->store(buf, length);
1893
2224
      }
1894
2225
      break;
1895
2226
 
1896
2227
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
2228
      session->client->store(STRING_WITH_LEN("status"));
 
2229
      session->client->store(STRING_WITH_LEN("OK"));
1899
2230
      break;
1900
2231
 
1901
2232
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
2233
      session->client->store(STRING_WITH_LEN("status"));
 
2234
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
2235
      break;
1905
2236
 
1906
2237
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
2238
      session->client->store(STRING_WITH_LEN("status"));
 
2239
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
2240
      open_for_modify= false;
1910
2241
      break;
1911
2242
 
1912
2243
    case HA_ADMIN_ALREADY_DONE:
1913
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1914
 
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
 
2244
      session->client->store(STRING_WITH_LEN("status"));
 
2245
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
2246
      break;
1916
2247
 
1917
2248
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
2249
      session->client->store(STRING_WITH_LEN("error"));
 
2250
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
2251
      fatal_error=1;
1921
2252
      break;
1922
2253
 
1923
2254
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1926
 
      break;
 
2255
      session->client->store(STRING_WITH_LEN("error"));
 
2256
      session->client->store(STRING_WITH_LEN("Invalid argument"));
 
2257
      break;
 
2258
 
 
2259
    case HA_ADMIN_TRY_ALTER:
 
2260
    {
 
2261
      /*
 
2262
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
2263
        "try with alter", so here we close the table, do an ALTER Table,
 
2264
        reopen the table and do ha_innobase::analyze() on it.
 
2265
      */
 
2266
      ha_autocommit_or_rollback(session, 0);
 
2267
      session->close_thread_tables();
 
2268
      TableList *save_next_local= table->next_local,
 
2269
                 *save_next_global= table->next_global;
 
2270
      table->next_local= table->next_global= 0;
 
2271
      result_code= mysql_recreate_table(session, table);
 
2272
      /*
 
2273
        mysql_recreate_table() can push OK or ERROR.
 
2274
        Clear 'OK' status. If there is an error, keep it:
 
2275
        we will store the error message in a result set row
 
2276
        and then clear.
 
2277
      */
 
2278
      if (session->main_da.is_ok())
 
2279
        session->main_da.reset_diagnostics_area();
 
2280
      ha_autocommit_or_rollback(session, 0);
 
2281
      session->close_thread_tables();
 
2282
      if (!result_code) // recreation went ok
 
2283
      {
 
2284
        if ((table->table= session->openTableLock(table, lock_type)) &&
 
2285
            ((result_code= table->table->cursor->ha_analyze(session, check_opt)) > 0))
 
2286
          result_code= 0; // analyze went ok
 
2287
      }
 
2288
      if (result_code) // either mysql_recreate_table or analyze failed
 
2289
      {
 
2290
        assert(session->is_error());
 
2291
        if (session->is_error())
 
2292
        {
 
2293
          const char *err_msg= session->main_da.message();
 
2294
          /* Hijack the row already in-progress. */
 
2295
          session->client->store(STRING_WITH_LEN("error"));
 
2296
          session->client->store(err_msg);
 
2297
          (void)session->client->flush();
 
2298
          /* Start off another row for HA_ADMIN_FAILED */
 
2299
          session->client->store(table_name);
 
2300
          session->client->store(operator_name);
 
2301
          session->clear_error();
 
2302
        }
 
2303
      }
 
2304
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
2305
      table->next_local= save_next_local;
 
2306
      table->next_global= save_next_global;
 
2307
      goto send_result_message;
 
2308
    }
 
2309
    case HA_ADMIN_NEEDS_UPGRADE:
 
2310
    case HA_ADMIN_NEEDS_ALTER:
 
2311
    {
 
2312
      char buf[ERRMSGSIZE];
 
2313
      uint32_t length;
 
2314
 
 
2315
      session->client->store(STRING_WITH_LEN("error"));
 
2316
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
2317
      session->client->store(buf, length);
 
2318
      fatal_error=1;
 
2319
      break;
 
2320
    }
1927
2321
 
1928
2322
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1929
2323
      {
1931
2325
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
2326
                             _("Unknown - internal error %d during operation"),
1933
2327
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
2328
        session->client->store(STRING_WITH_LEN("error"));
 
2329
        session->client->store(buf, length);
1936
2330
        fatal_error=1;
1937
2331
        break;
1938
2332
      }
1940
2334
    if (table->table)
1941
2335
    {
1942
2336
      if (fatal_error)
1943
 
      {
1944
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1945
 
      }
 
2337
        table->table->s->version=0;               // Force close of table
1946
2338
      else if (open_for_modify)
1947
2339
      {
1948
 
        if (table->table->getShare()->getType())
1949
 
        {
 
2340
        if (table->table->s->tmp_table)
1950
2341
          table->table->cursor->info(HA_STATUS_CONST);
1951
 
        }
1952
2342
        else
1953
2343
        {
1954
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1955
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1956
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
2344
          pthread_mutex_lock(&LOCK_open);
 
2345
          remove_table_from_cache(session, table->table->s->db.str,
 
2346
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
2347
          pthread_mutex_unlock(&LOCK_open);
1957
2348
        }
1958
2349
      }
1959
2350
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
2351
    ha_autocommit_or_rollback(session, 0);
1961
2352
    session->endTransaction(COMMIT);
1962
2353
    session->close_thread_tables();
1963
2354
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
2355
    if (session->client->flush())
1965
2356
      goto err;
1966
2357
  }
1967
2358
 
1969
2360
  return(false);
1970
2361
 
1971
2362
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
2363
  ha_autocommit_or_rollback(session, 1);
1973
2364
  session->endTransaction(ROLLBACK);
1974
2365
  session->close_thread_tables();                       // Shouldn't be needed
1975
2366
  if (table)
1977
2368
  return(true);
1978
2369
}
1979
2370
 
 
2371
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2372
{
 
2373
  return(mysql_admin_table(session, tables, check_opt,
 
2374
                           "optimize", TL_WRITE, 1,0,0,0,
 
2375
                           &Cursor::ha_optimize));
 
2376
}
 
2377
 
 
2378
/*
 
2379
  Create a table identical to the specified table
 
2380
 
 
2381
  SYNOPSIS
 
2382
    mysql_create_like_table()
 
2383
    session             Thread object
 
2384
    table       Table list element for target table
 
2385
    src_table   Table list element for source table
 
2386
    create_info Create info
 
2387
 
 
2388
  RETURN VALUES
 
2389
    false OK
 
2390
    true  error
 
2391
*/
 
2392
 
 
2393
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2394
                             drizzled::message::Table& create_table_proto,
 
2395
                             HA_CREATE_INFO *create_info)
 
2396
{
 
2397
  Table *name_lock= 0;
 
2398
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
2399
  uint32_t dst_path_length;
 
2400
  char *db= table->db;
 
2401
  char *table_name= table->table_name;
 
2402
  int  err;
 
2403
  bool res= true;
 
2404
  uint32_t not_used;
 
2405
  message::Table src_proto;
 
2406
 
 
2407
  /*
 
2408
    By opening source table we guarantee that it exists and no concurrent
 
2409
    DDL operation will mess with it. Later we also take an exclusive
 
2410
    name-lock on target table name, which makes copying of .frm cursor,
 
2411
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2412
    against concurrent DML and DDL operations on target table.
 
2413
    Thus by holding both these "locks" we ensure that our statement is
 
2414
    properly isolated from all concurrent operations which matter.
 
2415
  */
 
2416
  if (session->open_tables_from_list(&src_table, &not_used))
 
2417
    return true;
 
2418
 
 
2419
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
 
2420
 
 
2421
 
 
2422
  /*
 
2423
    Check that destination tables does not exist. Note that its name
 
2424
    was already checked when it was added to the table list.
 
2425
  */
 
2426
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2427
  {
 
2428
    if (session->find_temporary_table(db, table_name))
 
2429
      goto table_exists;
 
2430
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
 
2431
  }
 
2432
  else
 
2433
  {
 
2434
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
 
2435
      goto err;
 
2436
    if (!name_lock)
 
2437
      goto table_exists;
 
2438
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
2439
                                          db, table_name, false);
 
2440
    if (plugin::StorageEngine::getTableDefinition(*session, dst_path, db, table_name, false) == EEXIST)
 
2441
      goto table_exists;
 
2442
  }
 
2443
 
1980
2444
  /*
1981
2445
    Create a new table by copying from source table
1982
2446
 
1983
2447
    Altough exclusive name-lock on target table protects us from concurrent
1984
2448
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2449
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
2450
    LOCK_open in order to provide minimal atomicity against operations which
1987
2451
    disregard name-locks, like I_S implementation, for example. This is a
1988
2452
    temporary and should not be copied. Instead we should fix our code to
1989
2453
    always honor name-locks.
1990
2454
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
2455
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2456
    during the call to plugin::StorageEngine::createTable().
1993
2457
    See bug #28614 for more info.
1994
2458
  */
1995
 
static bool create_table_wrapper(Session &session,
1996
 
                                 const message::Table& create_table_proto,
1997
 
                                 identifier::Table::const_reference destination_identifier,
1998
 
                                 identifier::Table::const_reference source_identifier,
1999
 
                                 bool is_engine_set)
2000
 
{
2001
 
  // We require an additional table message because during parsing we used
2002
 
  // a "new" message and it will not have all of the information that the
2003
 
  // source table message would have.
2004
 
  message::Table new_table_message;
2005
 
  drizzled::error_t error;
2006
 
 
2007
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2008
 
 
2009
 
  if (not source_table_message)
2010
 
  {
2011
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  new_table_message.CopyFrom(*source_table_message);
2016
 
 
2017
 
  if (destination_identifier.isTmp())
2018
 
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
2459
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2460
  {
 
2461
    int protoerr= EEXIST;
 
2462
 
 
2463
    if (src_table->schema_table)
 
2464
    {
 
2465
      /* 
 
2466
        If engine was not specified and we are reading from the I_S, then we need to 
 
2467
        toss an error. This should go away later on when we straighten out the 
 
2468
        I_S engine.
 
2469
      */
 
2470
      if (! (create_info->used_fields & HA_CREATE_USED_ENGINE))
 
2471
      {
 
2472
        pthread_mutex_unlock(&LOCK_open);
 
2473
        my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2474
                 "INFORMATION_ENGINE",
 
2475
                 "TEMPORARY");
 
2476
        goto err;
 
2477
      }
 
2478
 
 
2479
      if (create_like_schema_frm(session, src_table, create_info, &src_proto))
 
2480
      {
 
2481
        pthread_mutex_unlock(&LOCK_open);
 
2482
        goto err;
 
2483
      }
 
2484
    }
 
2485
    else
 
2486
    {
 
2487
      protoerr= plugin::StorageEngine::getTableDefinition(*session,
 
2488
                                                          src_path,
 
2489
                                                          db,
 
2490
                                                          table_name,
 
2491
                                                          false,
 
2492
                                                          &src_proto);
 
2493
    }
 
2494
 
 
2495
    message::Table new_proto(src_proto);
 
2496
 
 
2497
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
2498
    {
 
2499
      message::Table::StorageEngine *protoengine;
 
2500
 
 
2501
      protoengine= new_proto.mutable_engine();
 
2502
      protoengine->set_name(create_table_proto.engine().name());
 
2503
    }
 
2504
 
 
2505
    if (protoerr == EEXIST)
 
2506
    {
 
2507
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
 
2508
                                                                       new_proto.engine().name());
 
2509
 
 
2510
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2511
      {
 
2512
        string dst_proto_path(dst_path);
 
2513
        dst_proto_path.append(".dfe");
 
2514
 
 
2515
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
 
2516
      }
 
2517
      else
 
2518
      {
 
2519
        protoerr= 0;
 
2520
      }
 
2521
    }
 
2522
 
 
2523
    if (protoerr)
 
2524
    {
 
2525
      if (my_errno == ENOENT)
 
2526
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2527
      else
 
2528
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2529
      pthread_mutex_unlock(&LOCK_open);
 
2530
      goto err;
 
2531
    }
 
2532
 
 
2533
    /*
 
2534
      As mysql_truncate don't work on a new table at this stage of
 
2535
      creation, instead create the table directly (for both normal
 
2536
      and temporary tables).
 
2537
    */
 
2538
    err= plugin::StorageEngine::createTable(*session, dst_path, db, table_name, *create_info, 
 
2539
                                            true, new_proto);
 
2540
  }
 
2541
  pthread_mutex_unlock(&LOCK_open);
 
2542
 
 
2543
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2544
  {
 
2545
    if (err || !session->open_temporary_table(dst_path, db, table_name))
 
2546
    {
 
2547
      (void) session->rm_temporary_table(create_info->db_type, dst_path);
 
2548
      goto err;
 
2549
    }
 
2550
  }
 
2551
  else if (err)
 
2552
  {
 
2553
    (void) quick_rm_table(*session, db,
 
2554
                          table_name, false);
 
2555
    goto err;
 
2556
  }
 
2557
 
 
2558
  /*
 
2559
    We have to write the query before we unlock the tables.
 
2560
  */
 
2561
  {
 
2562
    /*
 
2563
       Since temporary tables are not replicated under row-based
 
2564
       replication, CREATE TABLE ... LIKE ... needs special
 
2565
       treatement.  We have four cases to consider, according to the
 
2566
       following decision table:
 
2567
 
 
2568
           ==== ========= ========= ==============================
 
2569
           Case    Target    Source Write to binary log
 
2570
           ==== ========= ========= ==============================
 
2571
           1       normal    normal Original statement
 
2572
           2       normal temporary Generated statement
 
2573
           3    temporary    normal Nothing
 
2574
           4    temporary temporary Nothing
 
2575
           ==== ========= ========= ==============================
 
2576
    */
 
2577
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2578
    {
 
2579
      if (src_table->table->s->tmp_table)               // Case 2
 
2580
      {
 
2581
        char buf[2048];
 
2582
        String query(buf, sizeof(buf), system_charset_info);
 
2583
        query.length(0);  // Have to zero it since constructor doesn't
 
2584
 
 
2585
 
 
2586
        /*
 
2587
          Here we open the destination table, on which we already have
 
2588
          name-lock. This is needed for store_create_info() to work.
 
2589
          The table will be closed by unlink_open_table() at the end
 
2590
          of this function.
 
2591
        */
 
2592
        table->table= name_lock;
 
2593
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2594
        if (session->reopen_name_locked_table(table, false))
 
2595
        {
 
2596
          pthread_mutex_unlock(&LOCK_open);
 
2597
          goto err;
 
2598
        }
 
2599
        pthread_mutex_unlock(&LOCK_open);
 
2600
 
 
2601
        int result= store_create_info(table, &query, create_info);
 
2602
 
 
2603
        assert(result == 0); // store_create_info() always return 0
 
2604
        write_bin_log(session, query.ptr(), query.length());
 
2605
      }
 
2606
      else                                      // Case 1
 
2607
        write_bin_log(session, session->query, session->query_length);
 
2608
    }
 
2609
  }
 
2610
 
 
2611
  res= false;
 
2612
  goto err;
 
2613
 
 
2614
table_exists:
 
2615
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2616
  {
 
2617
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2618
    snprintf(warn_buff, sizeof(warn_buff),
 
2619
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
2620
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2621
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
2622
    res= false;
2020
2623
  }
2021
2624
  else
2022
 
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
2024
 
  }
2025
 
 
2026
 
  if (is_engine_set)
2027
 
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2029
 
  }
2030
 
 
2031
 
  { // We now do a selective copy of elements on to the new table.
2032
 
    new_table_message.set_name(create_table_proto.name());
2033
 
    new_table_message.set_schema(create_table_proto.schema());
2034
 
    new_table_message.set_catalog(create_table_proto.catalog());
2035
 
  }
2036
 
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2039
 
  {
2040
 
    if (new_table_message.fk_constraint(j).has_name())
2041
 
    {
2042
 
      std::string name(new_table_message.name());
2043
 
      char number[20];
2044
 
 
2045
 
      name.append("_ibfk_");
2046
 
      snprintf(number, sizeof(number), "%d", j+1);
2047
 
      name.append(number);
2048
 
 
2049
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
 
      pfkey->set_name(name);
2051
 
    }
2052
 
  }
2053
 
 
2054
 
  /*
2055
 
    As mysql_truncate don't work on a new table at this stage of
2056
 
    creation, instead create the table directly (for both normal and temporary tables).
2057
 
  */
2058
 
  bool success= plugin::StorageEngine::createTable(session,
2059
 
                                                   destination_identifier,
2060
 
                                                   new_table_message);
2061
 
 
2062
 
  if (success && not destination_identifier.isTmp())
2063
 
  {
2064
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2065
 
    transaction_services.createTable(session, new_table_message);
2066
 
  }
2067
 
 
2068
 
  return success;
2069
 
}
2070
 
 
2071
 
/*
2072
 
  Create a table identical to the specified table
2073
 
 
2074
 
  SYNOPSIS
2075
 
    create_like_table()
2076
 
    session             Thread object
2077
 
    table       Table list element for target table
2078
 
    src_table   Table list element for source table
2079
 
    create_info Create info
2080
 
 
2081
 
  RETURN VALUES
2082
 
    false OK
2083
 
    true  error
2084
 
*/
2085
 
 
2086
 
bool create_like_table(Session* session,
2087
 
                       identifier::Table::const_reference destination_identifier,
2088
 
                       identifier::Table::const_reference source_identifier,
2089
 
                       message::Table &create_table_proto,
2090
 
                       bool is_if_not_exists,
2091
 
                       bool is_engine_set)
2092
 
{
2093
 
  bool res= true;
2094
 
  bool table_exists= false;
2095
 
 
2096
 
  /*
2097
 
    Check that destination tables does not exist. Note that its name
2098
 
    was already checked when it was added to the table list.
2099
 
 
2100
 
    For temporary tables we don't aim to grab locks.
2101
 
  */
2102
 
  if (destination_identifier.isTmp())
2103
 
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
2105
 
    {
2106
 
      table_exists= true;
2107
 
    }
2108
 
    else
2109
 
    {
2110
 
      bool was_created= create_table_wrapper(*session,
2111
 
                                             create_table_proto,
2112
 
                                             destination_identifier,
2113
 
                                             source_identifier,
2114
 
                                             is_engine_set);
2115
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2116
 
      {
2117
 
        (void) session->rm_temporary_table(destination_identifier, true);
2118
 
      }
2119
 
      else if (not session->open_temporary_table(destination_identifier))
2120
 
      {
2121
 
        // We created, but we can't open... also, a hack.
2122
 
        (void) session->rm_temporary_table(destination_identifier, true);
2123
 
      }
2124
 
      else
2125
 
      {
2126
 
        res= false;
2127
 
      }
2128
 
    }
2129
 
  }
2130
 
  else // Standard table which will require locks.
2131
 
  {
2132
 
    Table *name_lock= 0;
2133
 
 
2134
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2135
 
    {
2136
 
      if (name_lock)
2137
 
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
 
        session->unlink_open_table(name_lock);
2140
 
      }
2141
 
 
2142
 
      return res;
2143
 
    }
2144
 
 
2145
 
    if (not name_lock)
2146
 
    {
2147
 
      table_exists= true;
2148
 
    }
2149
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2150
 
    {
2151
 
      table_exists= true;
2152
 
    }
2153
 
    else // Otherwise we create the table
2154
 
    {
2155
 
      bool was_created;
2156
 
      {
2157
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
 
                                          source_identifier, is_engine_set);
2160
 
      }
2161
 
 
2162
 
      // So we blew the creation of the table, and we scramble to clean up
2163
 
      // anything that might have been created (read... it is a hack)
2164
 
      if (not was_created)
2165
 
      {
2166
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2167
 
      } 
2168
 
      else
2169
 
      {
2170
 
        res= false;
2171
 
      }
2172
 
    }
2173
 
 
2174
 
    if (name_lock)
2175
 
    {
2176
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2177
 
      session->unlink_open_table(name_lock);
2178
 
    }
2179
 
  }
2180
 
 
2181
 
  if (table_exists)
2182
 
  {
2183
 
    if (is_if_not_exists)
2184
 
    {
2185
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
 
      snprintf(warn_buff, sizeof(warn_buff),
2187
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2188
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2190
 
      return false;
2191
 
    }
2192
 
 
2193
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2194
 
 
2195
 
    return true;
2196
 
  }
2197
 
 
2198
 
  return res;
2199
 
}
2200
 
 
2201
 
 
2202
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2625
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2626
 
 
2627
err:
 
2628
  if (name_lock)
 
2629
  {
 
2630
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2631
    session->unlink_open_table(name_lock);
 
2632
    pthread_mutex_unlock(&LOCK_open);
 
2633
  }
 
2634
  return(res);
 
2635
}
 
2636
 
 
2637
 
 
2638
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
2639
{
2204
2640
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
2641
 
2206
 
  return(admin_table(session, tables, check_opt,
2207
 
                                "analyze", lock_type, true,
 
2642
  return(mysql_admin_table(session, tables, check_opt,
 
2643
                                "analyze", lock_type, 1, 0, 0, 0,
2208
2644
                                &Cursor::ha_analyze));
2209
2645
}
2210
2646
 
2211
2647
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2648
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
2649
{
2214
2650
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
2651
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2652
  return(mysql_admin_table(session, tables, check_opt,
2217
2653
                                "check", lock_type,
2218
 
                                false,
 
2654
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
2219
2655
                                &Cursor::ha_check));
2220
2656
}
2221
2657
 
2222
 
} /* namespace drizzled */
 
2658
/*
 
2659
  Recreates tables by calling drizzled::alter_table().
 
2660
 
 
2661
  SYNOPSIS
 
2662
    mysql_recreate_table()
 
2663
    session                     Thread Cursor
 
2664
    tables              Tables to recreate
 
2665
 
 
2666
 RETURN
 
2667
    Like drizzled::alter_table().
 
2668
*/
 
2669
bool mysql_recreate_table(Session *session, TableList *table_list)
 
2670
{
 
2671
  HA_CREATE_INFO create_info;
 
2672
  AlterInfo alter_info;
 
2673
  message::Table table_proto;
 
2674
 
 
2675
  assert(!table_list->next_global);
 
2676
  /*
 
2677
    table_list->table has been closed and freed. Do not reference
 
2678
    uninitialized data. open_tables() could fail.
 
2679
  */
 
2680
  table_list->table= NULL;
 
2681
 
 
2682
  memset(&create_info, 0, sizeof(create_info));
 
2683
  create_info.row_type=ROW_TYPE_NOT_USED;
 
2684
  create_info.default_table_charset=default_charset_info;
 
2685
  /* Force alter table to recreate table */
 
2686
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
2687
  alter_info.flags.set(ALTER_RECREATE);
 
2688
  return(alter_table(session, NULL, NULL, &create_info, &table_proto,
 
2689
                     table_list, &alter_info, 0,
 
2690
                     (order_st *) 0, 0));
 
2691
}
 
2692
 
 
2693
 
 
2694
bool mysql_checksum_table(Session *session, TableList *tables,
 
2695
                          HA_CHECK_OPT *check_opt)
 
2696
{
 
2697
  TableList *table;
 
2698
  List<Item> field_list;
 
2699
  Item *item;
 
2700
 
 
2701
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
2702
  item->maybe_null= 1;
 
2703
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
2704
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
2705
  item->maybe_null= 1;
 
2706
  if (session->client->sendFields(&field_list))
 
2707
    return true;
 
2708
 
 
2709
  /* Open one table after the other to keep lock time as short as possible. */
 
2710
  for (table= tables; table; table= table->next_local)
 
2711
  {
 
2712
    char table_name[NAME_LEN*2+2];
 
2713
    Table *t;
 
2714
 
 
2715
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2716
 
 
2717
    t= table->table= session->openTableLock(table, TL_READ);
 
2718
    session->clear_error();                     // these errors shouldn't get client
 
2719
 
 
2720
    session->client->store(table_name);
 
2721
 
 
2722
    if (!t)
 
2723
    {
 
2724
      /* Table didn't exist */
 
2725
      session->client->store();
 
2726
      session->clear_error();
 
2727
    }
 
2728
    else
 
2729
    {
 
2730
      if (t->cursor->ha_table_flags() & HA_HAS_CHECKSUM &&
 
2731
          !(check_opt->flags & T_EXTEND))
 
2732
        session->client->store((uint64_t)t->cursor->checksum());
 
2733
      else if (!(t->cursor->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
2734
               (check_opt->flags & T_QUICK))
 
2735
        session->client->store();
 
2736
      else
 
2737
      {
 
2738
        /* calculating table's checksum */
 
2739
        ha_checksum crc= 0;
 
2740
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2741
 
 
2742
        t->use_all_columns();
 
2743
 
 
2744
        if (t->cursor->ha_rnd_init(1))
 
2745
          session->client->store();
 
2746
        else
 
2747
        {
 
2748
          for (;;)
 
2749
          {
 
2750
            ha_checksum row_crc= 0;
 
2751
            int error= t->cursor->rnd_next(t->record[0]);
 
2752
            if (unlikely(error))
 
2753
            {
 
2754
              if (error == HA_ERR_RECORD_DELETED)
 
2755
                continue;
 
2756
              break;
 
2757
            }
 
2758
            if (t->s->null_bytes)
 
2759
            {
 
2760
              /* fix undefined null bits */
 
2761
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
2762
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
2763
                t->record[0][0] |= 1;
 
2764
 
 
2765
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
2766
            }
 
2767
 
 
2768
            for (uint32_t i= 0; i < t->s->fields; i++ )
 
2769
            {
 
2770
              Field *f= t->field[i];
 
2771
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
 
2772
                  (f->type() == DRIZZLE_TYPE_VARCHAR))
 
2773
              {
 
2774
                String tmp;
 
2775
                f->val_str(&tmp);
 
2776
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
 
2777
              }
 
2778
              else
 
2779
                row_crc= my_checksum(row_crc, f->ptr,
 
2780
                                     f->pack_length());
 
2781
            }
 
2782
 
 
2783
            crc+= row_crc;
 
2784
          }
 
2785
          session->client->store((uint64_t)crc);
 
2786
          t->cursor->ha_rnd_end();
 
2787
        }
 
2788
      }
 
2789
      session->clear_error();
 
2790
      session->close_thread_tables();
 
2791
      table->table=0;                           // For query cache
 
2792
    }
 
2793
    if (session->client->flush())
 
2794
      goto err;
 
2795
  }
 
2796
 
 
2797
  session->my_eof();
 
2798
  return(false);
 
2799
 
 
2800
 err:
 
2801
  session->close_thread_tables();                       // Shouldn't be needed
 
2802
  if (table)
 
2803
    table->table=0;
 
2804
  return(true);
 
2805
}
 
2806
 
 
2807
bool check_engine(Session *session, const char *table_name,
 
2808
                         HA_CREATE_INFO *create_info)
 
2809
{
 
2810
  plugin::StorageEngine **new_engine= &create_info->db_type;
 
2811
  plugin::StorageEngine *req_engine= *new_engine;
 
2812
  if (!req_engine->is_enabled())
 
2813
  {
 
2814
    string engine_name= req_engine->getName();
 
2815
    my_error(ER_FEATURE_DISABLED,MYF(0),
 
2816
             engine_name.c_str(), engine_name.c_str());
 
2817
             
 
2818
    return true;
 
2819
  }
 
2820
 
 
2821
  if (req_engine && req_engine != *new_engine)
 
2822
  {
 
2823
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2824
                       ER_WARN_USING_OTHER_HANDLER,
 
2825
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
2826
                       plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2827
                       table_name);
 
2828
  }
 
2829
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
2830
      (*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
 
2831
  {
 
2832
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
2833
    {
 
2834
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2835
               plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2836
               "TEMPORARY");
 
2837
      *new_engine= 0;
 
2838
      return true;
 
2839
    }
 
2840
    *new_engine= myisam_engine;
 
2841
  }
 
2842
  if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2843
     && (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
 
2844
  {
 
2845
    my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2846
             plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2847
             "non-TEMPORARY");
 
2848
    *new_engine= 0;
 
2849
    return true;
 
2850
  }
 
2851
 
 
2852
  return false;
 
2853
}