~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_table.cc

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:54:00 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717175400-xm2aazihjra8mdzq
Removal of DBUG from libdrizzle/ - Round 2

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>
19
 
#include <plugin/myisam/myisam.h>
20
 
#include <drizzled/show.h>
21
 
#include <drizzled/error.h>
22
 
#include <drizzled/gettext.h>
23
 
#include <drizzled/data_home.h>
24
 
#include <drizzled/sql_parse.h>
25
 
#include <drizzled/my_hash.h>
26
 
#include <drizzled/sql_lex.h>
27
 
#include <drizzled/session.h>
28
 
#include <drizzled/sql_base.h>
29
 
#include <drizzled/strfunc.h>
30
 
#include <drizzled/lock.h>
31
 
#include <drizzled/unireg.h>
32
 
#include <drizzled/item/int.h>
33
 
#include <drizzled/item/empty_string.h>
34
 
#include <drizzled/transaction_services.h>
35
 
#include <drizzled/transaction_services.h>
36
 
#include <drizzled/table_proto.h>
37
 
#include <drizzled/plugin/client.h>
38
 
#include <drizzled/identifier.h>
39
 
#include <drizzled/internal/m_string.h>
40
 
#include <drizzled/global_charset_info.h>
41
 
#include <drizzled/charset.h>
42
 
 
43
 
#include <drizzled/definition/cache.h>
44
 
 
45
 
#include <drizzled/statement/alter_table.h>
46
 
#include <drizzled/sql_table.h>
47
 
#include <drizzled/pthread_globals.h>
48
 
#include <drizzled/typelib.h>
49
 
#include <drizzled/plugin/storage_engine.h>
50
 
 
51
 
#include <algorithm>
52
 
#include <sstream>
53
 
 
54
 
#include <boost/unordered_set.hpp>
55
 
 
56
 
using namespace std;
57
 
 
58
 
namespace drizzled
59
 
{
60
 
 
61
 
bool is_primary_key(KeyInfo *key_info)
62
 
{
63
 
  static const char * primary_key_name="PRIMARY";
64
 
  return (strcmp(key_info->name, primary_key_name)==0);
65
 
}
66
 
 
67
 
const char* is_primary_key_name(const char* key_name)
68
 
{
69
 
  static const char * primary_key_name="PRIMARY";
70
 
  if (strcmp(key_name, primary_key_name)==0)
71
 
    return key_name;
72
 
  else
73
 
    return NULL;
74
 
}
75
 
 
76
 
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
77
 
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
78
 
 
79
 
static bool prepare_blob_field(Session *session, CreateField *sql_field);
80
 
 
81
 
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
82
 
{
83
 
  /*
84
 
    If the table character set was not given explicitly,
85
 
    let's fetch the database default character set and
86
 
    apply it to the table.
87
 
  */
88
 
  identifier::Schema identifier(db);
89
 
  if (create_info->default_table_charset == NULL)
90
 
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
91
 
}
 
18
#include "mysql_priv.h"
 
19
#include <hash.h>
 
20
#include <myisam.h>
 
21
#include <my_dir.h>
 
22
#include "sql_show.h"
 
23
 
 
24
int creating_table= 0;        // How many mysql_create_table are running
 
25
 
 
26
const char *primary_key_name="PRIMARY";
 
27
 
 
28
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 
29
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
 
30
static int copy_data_between_tables(TABLE *from,TABLE *to,
 
31
                                    List<Create_field> &create, bool ignore,
 
32
                                    uint order_num, ORDER *order,
 
33
                                    ha_rows *copied,ha_rows *deleted,
 
34
                                    enum enum_enable_or_disable keys_onoff,
 
35
                                    bool error_if_not_empty);
 
36
 
 
37
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
 
38
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
 
39
static int
 
40
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 
41
                           Alter_info *alter_info,
 
42
                           bool tmp_table,
 
43
                               uint *db_options,
 
44
                               handler *file, KEY **key_info_buffer,
 
45
                               uint *key_count, int select_field_count);
 
46
static bool
 
47
mysql_prepare_alter_table(THD *thd, TABLE *table,
 
48
                          HA_CREATE_INFO *create_info,
 
49
                          Alter_info *alter_info);
 
50
 
 
51
/*
 
52
  Translate a file name to a table name (WL #1324).
 
53
 
 
54
  SYNOPSIS
 
55
    filename_to_tablename()
 
56
      from                      The file name in my_charset_filename.
 
57
      to                OUT     The table name in system_charset_info.
 
58
      to_length                 The size of the table name buffer.
 
59
 
 
60
  RETURN
 
61
    Table name length.
 
62
*/
 
63
uint filename_to_tablename(const char *from, char *to, uint to_length)
 
64
{
 
65
  uint errors;
 
66
  uint res;
 
67
 
 
68
  if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
 
69
  {
 
70
    /* Temporary table name. */
 
71
    res= (strnmov(to, from, to_length) - to);
 
72
  }
 
73
  else
 
74
  {
 
75
    res= strconvert(&my_charset_filename, from,
 
76
                    system_charset_info,  to, to_length, &errors);
 
77
    if (errors) // Old 5.0 name
 
78
    {
 
79
      res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX,  from, NullS) -
 
80
            to);
 
81
      sql_print_error("Invalid (old?) table or database name '%s'", from);
 
82
      /*
 
83
        TODO: add a stored procedure for fix table and database names,
 
84
        and mention its name in error log.
 
85
      */
 
86
    }
 
87
  }
 
88
 
 
89
  return(res);
 
90
}
 
91
 
 
92
 
 
93
/*
 
94
  Translate a table name to a file name (WL #1324).
 
95
 
 
96
  SYNOPSIS
 
97
    tablename_to_filename()
 
98
      from                      The table name in system_charset_info.
 
99
      to                OUT     The file name in my_charset_filename.
 
100
      to_length                 The size of the file name buffer.
 
101
 
 
102
  RETURN
 
103
    File name length.
 
104
*/
 
105
 
 
106
uint tablename_to_filename(const char *from, char *to, uint to_length)
 
107
{
 
108
  uint errors, length;
 
109
 
 
110
  if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
 
111
                                 MYSQL50_TABLE_NAME_PREFIX_LENGTH))
 
112
    return((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
 
113
                                to_length-1) -
 
114
                        (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
 
115
  length= strconvert(system_charset_info, from,
 
116
                     &my_charset_filename, to, to_length, &errors);
 
117
  if (check_if_legal_tablename(to) &&
 
118
      length + 4 < to_length)
 
119
  {
 
120
    memcpy(to + length, "@@@", 4);
 
121
    length+= 3;
 
122
  }
 
123
  return(length);
 
124
}
 
125
 
 
126
 
 
127
/*
 
128
  Creates path to a file: mysql_data_dir/db/table.ext
 
129
 
 
130
  SYNOPSIS
 
131
   build_table_filename()
 
132
     buff                       Where to write result in my_charset_filename.
 
133
                                This may be the same as table_name.
 
134
     bufflen                    buff size
 
135
     db                         Database name in system_charset_info.
 
136
     table_name                 Table name in system_charset_info.
 
137
     ext                        File extension.
 
138
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
139
                                table_name is temporary, do not change.
 
140
 
 
141
  NOTES
 
142
 
 
143
    Uses database and table name, and extension to create
 
144
    a file name in mysql_data_dir. Database and table
 
145
    names are converted from system_charset_info into "fscs".
 
146
    Unless flags indicate a temporary table name.
 
147
    'db' is always converted.
 
148
    'ext' is not converted.
 
149
 
 
150
    The conversion suppression is required for ALTER TABLE. This
 
151
    statement creates intermediate tables. These are regular
 
152
    (non-temporary) tables with a temporary name. Their path names must
 
153
    be derivable from the table name. So we cannot use
 
154
    build_tmptable_filename() for them.
 
155
 
 
156
  RETURN
 
157
    path length
 
158
*/
 
159
 
 
160
uint build_table_filename(char *buff, size_t bufflen, const char *db,
 
161
                          const char *table_name, const char *ext, uint flags)
 
162
{
 
163
  char dbbuff[FN_REFLEN];
 
164
  char tbbuff[FN_REFLEN];
 
165
 
 
166
  if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
167
    strnmov(tbbuff, table_name, sizeof(tbbuff));
 
168
  else
 
169
    VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
 
170
 
 
171
  VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
 
172
 
 
173
  char *end = buff + bufflen;
 
174
  /* Don't add FN_ROOTDIR if mysql_data_home already includes it */
 
175
  char *pos = strnmov(buff, mysql_data_home, bufflen);
 
176
  int rootdir_len= strlen(FN_ROOTDIR);
 
177
  if (pos - rootdir_len >= buff &&
 
178
      memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
 
179
    pos= strnmov(pos, FN_ROOTDIR, end - pos);
 
180
  pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
 
181
#ifdef USE_SYMDIR
 
182
  unpack_dirname(buff, buff);
 
183
  pos= strend(buff);
 
184
#endif
 
185
  pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
 
186
 
 
187
  return(pos - buff);
 
188
}
 
189
 
 
190
 
 
191
/*
 
192
  Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
 
193
 
 
194
  SYNOPSIS
 
195
   build_tmptable_filename()
 
196
     thd                        The thread handle.
 
197
     buff                       Where to write result in my_charset_filename.
 
198
     bufflen                    buff size
 
199
 
 
200
  NOTES
 
201
 
 
202
    Uses current_pid, thread_id, and tmp_table counter to create
 
203
    a file name in mysql_tmpdir.
 
204
 
 
205
  RETURN
 
206
    path length
 
207
*/
 
208
 
 
209
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
 
210
{
 
211
 
 
212
  char *p= strnmov(buff, mysql_tmpdir, bufflen);
 
213
  snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
 
214
              tmp_file_prefix, current_pid,
 
215
              thd->thread_id, thd->tmp_table++, reg_ext);
 
216
 
 
217
  if (lower_case_table_names)
 
218
  {
 
219
    /* Convert all except tmpdir to lower case */
 
220
    my_casedn_str(files_charset_info, p);
 
221
  }
 
222
 
 
223
  uint length= unpack_filename(buff, buff);
 
224
  return(length);
 
225
}
 
226
 
 
227
/*
 
228
--------------------------------------------------------------------------
 
229
 
 
230
   MODULE: DDL log
 
231
   -----------------
 
232
 
 
233
   This module is used to ensure that we can recover from crashes that occur
 
234
   in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
 
235
   We need to ensure that both t1 and t2 are dropped and not only t1 and
 
236
   also that each table drop is entirely done and not "half-baked".
 
237
 
 
238
   To support this we create log entries for each meta-data statement in the
 
239
   ddl log while we are executing. These entries are dropped when the
 
240
   operation is completed.
 
241
 
 
242
   At recovery those entries that were not completed will be executed.
 
243
 
 
244
   There is only one ddl log in the system and it is protected by a mutex
 
245
   and there is a global struct that contains information about its current
 
246
   state.
 
247
 
 
248
   History:
 
249
   First version written in 2006 by Mikael Ronstrom
 
250
--------------------------------------------------------------------------
 
251
*/
 
252
 
 
253
 
 
254
struct st_global_ddl_log
 
255
{
 
256
  /*
 
257
    We need to adjust buffer size to be able to handle downgrades/upgrades
 
258
    where IO_SIZE has changed. We'll set the buffer size such that we can
 
259
    handle that the buffer size was upto 4 times bigger in the version
 
260
    that wrote the DDL log.
 
261
  */
 
262
  char file_entry_buf[4*IO_SIZE];
 
263
  char file_name_str[FN_REFLEN];
 
264
  char *file_name;
 
265
  DDL_LOG_MEMORY_ENTRY *first_free;
 
266
  DDL_LOG_MEMORY_ENTRY *first_used;
 
267
  uint num_entries;
 
268
  File file_id;
 
269
  uint name_len;
 
270
  uint io_size;
 
271
  bool inited;
 
272
  bool do_release;
 
273
  bool recovery_phase;
 
274
  st_global_ddl_log() : inited(false), do_release(false) {}
 
275
};
 
276
 
 
277
st_global_ddl_log global_ddl_log;
 
278
 
 
279
pthread_mutex_t LOCK_gdl;
 
280
 
 
281
#define DDL_LOG_ENTRY_TYPE_POS 0
 
282
#define DDL_LOG_ACTION_TYPE_POS 1
 
283
#define DDL_LOG_PHASE_POS 2
 
284
#define DDL_LOG_NEXT_ENTRY_POS 4
 
285
#define DDL_LOG_NAME_POS 8
 
286
 
 
287
#define DDL_LOG_NUM_ENTRY_POS 0
 
288
#define DDL_LOG_NAME_LEN_POS 4
 
289
#define DDL_LOG_IO_SIZE_POS 8
 
290
 
 
291
/*
 
292
  Read one entry from ddl log file
 
293
  SYNOPSIS
 
294
    read_ddl_log_file_entry()
 
295
    entry_no                     Entry number to read
 
296
  RETURN VALUES
 
297
    true                         Error
 
298
    false                        Success
 
299
*/
 
300
 
 
301
static bool read_ddl_log_file_entry(uint entry_no)
 
302
{
 
303
  bool error= false;
 
304
  File file_id= global_ddl_log.file_id;
 
305
  uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
 
306
  ssize_t io_size= (ssize_t)global_ddl_log.io_size;
 
307
  
 
308
  if (pread(file_id, file_entry_buf, io_size, io_size * entry_no) != io_size)
 
309
    error= true;
 
310
  return(error);
 
311
}
 
312
 
 
313
 
 
314
/*
 
315
  Write one entry from ddl log file
 
316
  SYNOPSIS
 
317
    write_ddl_log_file_entry()
 
318
    entry_no                     Entry number to read
 
319
  RETURN VALUES
 
320
    true                         Error
 
321
    false                        Success
 
322
*/
 
323
 
 
324
static bool write_ddl_log_file_entry(uint entry_no)
 
325
{
 
326
  bool error= false;
 
327
  File file_id= global_ddl_log.file_id;
 
328
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
329
 
 
330
  if (pwrite(file_id, (uchar*)file_entry_buf,
 
331
                IO_SIZE, IO_SIZE * entry_no) != IO_SIZE)
 
332
    error= true;
 
333
  return(error);
 
334
}
 
335
 
 
336
 
 
337
/*
 
338
  Write ddl log header
 
339
  SYNOPSIS
 
340
    write_ddl_log_header()
 
341
  RETURN VALUES
 
342
    true                      Error
 
343
    false                     Success
 
344
*/
 
345
 
 
346
static bool write_ddl_log_header()
 
347
{
 
348
  uint16 const_var;
 
349
  bool error= false;
 
350
 
 
351
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
 
352
            global_ddl_log.num_entries);
 
353
  const_var= FN_LEN;
 
354
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
 
355
            (ulong) const_var);
 
356
  const_var= IO_SIZE;
 
357
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
 
358
            (ulong) const_var);
 
359
  if (write_ddl_log_file_entry(0UL))
 
360
  {
 
361
    sql_print_error("Error writing ddl log header");
 
362
    return(true);
 
363
  }
 
364
  VOID(sync_ddl_log());
 
365
  return(error);
 
366
}
 
367
 
 
368
 
 
369
/*
 
370
  Create ddl log file name
 
371
  SYNOPSIS
 
372
    create_ddl_log_file_name()
 
373
    file_name                   Filename setup
 
374
  RETURN VALUES
 
375
    NONE
 
376
*/
 
377
 
 
378
static inline void create_ddl_log_file_name(char *file_name)
 
379
{
 
380
  strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
 
381
}
 
382
 
 
383
 
 
384
/*
 
385
  Read header of ddl log file
 
386
  SYNOPSIS
 
387
    read_ddl_log_header()
 
388
  RETURN VALUES
 
389
    > 0                  Last entry in ddl log
 
390
    0                    No entries in ddl log
 
391
  DESCRIPTION
 
392
    When we read the ddl log header we get information about maximum sizes
 
393
    of names in the ddl log and we also get information about the number
 
394
    of entries in the ddl log.
 
395
*/
 
396
 
 
397
static uint read_ddl_log_header()
 
398
{
 
399
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
400
  char file_name[FN_REFLEN];
 
401
  uint entry_no;
 
402
  bool successful_open= false;
 
403
 
 
404
  create_ddl_log_file_name(file_name);
 
405
  if ((global_ddl_log.file_id= my_open(file_name,
 
406
                                        O_RDWR | O_BINARY, MYF(0))) >= 0)
 
407
  {
 
408
    if (read_ddl_log_file_entry(0UL))
 
409
    {
 
410
      /* Write message into error log */
 
411
      sql_print_error("Failed to read ddl log file in recovery");
 
412
    }
 
413
    else
 
414
      successful_open= true;
 
415
  }
 
416
  entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
 
417
  global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
 
418
  if (successful_open)
 
419
  {
 
420
    global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
 
421
    assert(global_ddl_log.io_size <=
 
422
                sizeof(global_ddl_log.file_entry_buf));
 
423
  }
 
424
  else
 
425
  {
 
426
    entry_no= 0;
 
427
  }
 
428
  global_ddl_log.first_free= NULL;
 
429
  global_ddl_log.first_used= NULL;
 
430
  global_ddl_log.num_entries= 0;
 
431
  VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
 
432
  global_ddl_log.do_release= true;
 
433
  return(entry_no);
 
434
}
 
435
 
 
436
 
 
437
/*
 
438
  Read a ddl log entry
 
439
  SYNOPSIS
 
440
    read_ddl_log_entry()
 
441
    read_entry               Number of entry to read
 
442
    out:entry_info           Information from entry
 
443
  RETURN VALUES
 
444
    true                     Error
 
445
    false                    Success
 
446
  DESCRIPTION
 
447
    Read a specified entry in the ddl log
 
448
*/
 
449
 
 
450
bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
 
451
{
 
452
  char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
 
453
  uint inx;
 
454
  uchar single_char;
 
455
 
 
456
  if (read_ddl_log_file_entry(read_entry))
 
457
  {
 
458
    return(true);
 
459
  }
 
460
  ddl_log_entry->entry_pos= read_entry;
 
461
  single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
 
462
  ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
 
463
  single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
 
464
  ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
 
465
  ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
 
466
  ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
 
467
  ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
 
468
  inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
 
469
  ddl_log_entry->from_name= &file_entry_buf[inx];
 
470
  inx+= global_ddl_log.name_len;
 
471
  ddl_log_entry->handler_name= &file_entry_buf[inx];
 
472
  return(false);
 
473
}
 
474
 
 
475
 
 
476
/*
 
477
  Initialise ddl log
 
478
  SYNOPSIS
 
479
    init_ddl_log()
 
480
 
 
481
  DESCRIPTION
 
482
    Write the header of the ddl log file and length of names. Also set
 
483
    number of entries to zero.
 
484
 
 
485
  RETURN VALUES
 
486
    true                     Error
 
487
    false                    Success
 
488
*/
 
489
 
 
490
static bool init_ddl_log()
 
491
{
 
492
  char file_name[FN_REFLEN];
 
493
 
 
494
  if (global_ddl_log.inited)
 
495
    goto end;
 
496
 
 
497
  global_ddl_log.io_size= IO_SIZE;
 
498
  create_ddl_log_file_name(file_name);
 
499
  if ((global_ddl_log.file_id= my_create(file_name,
 
500
                                         CREATE_MODE,
 
501
                                         O_RDWR | O_TRUNC | O_BINARY,
 
502
                                         MYF(MY_WME))) < 0)
 
503
  {
 
504
    /* Couldn't create ddl log file, this is serious error */
 
505
    sql_print_error("Failed to open ddl log file");
 
506
    return(true);
 
507
  }
 
508
  global_ddl_log.inited= true;
 
509
  if (write_ddl_log_header())
 
510
  {
 
511
    VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
 
512
    global_ddl_log.inited= false;
 
513
    return(true);
 
514
  }
 
515
 
 
516
end:
 
517
  return(false);
 
518
}
 
519
 
 
520
 
 
521
/*
 
522
  Execute one action in a ddl log entry
 
523
  SYNOPSIS
 
524
    execute_ddl_log_action()
 
525
    ddl_log_entry              Information in action entry to execute
 
526
  RETURN VALUES
 
527
    true                       Error
 
528
    false                      Success
 
529
*/
 
530
 
 
531
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
 
532
{
 
533
  bool frm_action= false;
 
534
  LEX_STRING handler_name;
 
535
  handler *file= NULL;
 
536
  MEM_ROOT mem_root;
 
537
  int error= true;
 
538
  char to_path[FN_REFLEN];
 
539
  char from_path[FN_REFLEN];
 
540
  handlerton *hton;
 
541
 
 
542
  if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
 
543
  {
 
544
    return(false);
 
545
  }
 
546
  handler_name.str= (char*)ddl_log_entry->handler_name;
 
547
  handler_name.length= strlen(ddl_log_entry->handler_name);
 
548
  init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); 
 
549
  if (!strcmp(ddl_log_entry->handler_name, reg_ext))
 
550
    frm_action= true;
 
551
  else
 
552
  {
 
553
    plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
 
554
    if (!plugin)
 
555
    {
 
556
      my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
 
557
      goto error;
 
558
    }
 
559
    hton= plugin_data(plugin, handlerton*);
 
560
    file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
 
561
    if (!file)
 
562
    {
 
563
      my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
564
      goto error;
 
565
    }
 
566
  }
 
567
  switch (ddl_log_entry->action_type)
 
568
  {
 
569
    case DDL_LOG_REPLACE_ACTION:
 
570
    case DDL_LOG_DELETE_ACTION:
 
571
    {
 
572
      if (ddl_log_entry->phase == 0)
 
573
      {
 
574
        if (frm_action)
 
575
        {
 
576
          strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
 
577
          if ((error= my_delete(to_path, MYF(MY_WME))))
 
578
          {
 
579
            if (my_errno != ENOENT)
 
580
              break;
 
581
          }
 
582
        }
 
583
        else
 
584
        {
 
585
          if ((error= file->ha_delete_table(ddl_log_entry->name)))
 
586
          {
 
587
            if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
 
588
              break;
 
589
          }
 
590
        }
 
591
        if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
 
592
          break;
 
593
        VOID(sync_ddl_log());
 
594
        error= false;
 
595
        if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
 
596
          break;
 
597
      }
 
598
      assert(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
 
599
      /*
 
600
        Fall through and perform the rename action of the replace
 
601
        action. We have already indicated the success of the delete
 
602
        action in the log entry by stepping up the phase.
 
603
      */
 
604
    }
 
605
    case DDL_LOG_RENAME_ACTION:
 
606
    {
 
607
      error= true;
 
608
      if (frm_action)
 
609
      {
 
610
        strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
 
611
        strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
 
612
        if (my_rename(from_path, to_path, MYF(MY_WME)))
 
613
          break;
 
614
      }
 
615
      else
 
616
      {
 
617
        if (file->ha_rename_table(ddl_log_entry->from_name,
 
618
                                  ddl_log_entry->name))
 
619
          break;
 
620
      }
 
621
      if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
 
622
        break;
 
623
      VOID(sync_ddl_log());
 
624
      error= false;
 
625
      break;
 
626
    }
 
627
    default:
 
628
      assert(0);
 
629
      break;
 
630
  }
 
631
  delete file;
 
632
error:
 
633
  free_root(&mem_root, MYF(0)); 
 
634
  return(error);
 
635
}
 
636
 
 
637
 
 
638
/*
 
639
  Get a free entry in the ddl log
 
640
  SYNOPSIS
 
641
    get_free_ddl_log_entry()
 
642
    out:active_entry                A ddl log memory entry returned
 
643
  RETURN VALUES
 
644
    true                       Error
 
645
    false                      Success
 
646
*/
 
647
 
 
648
static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
 
649
                                   bool *write_header)
 
650
{
 
651
  DDL_LOG_MEMORY_ENTRY *used_entry;
 
652
  DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
 
653
 
 
654
  if (global_ddl_log.first_free == NULL)
 
655
  {
 
656
    if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
 
657
                              sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
 
658
    {
 
659
      sql_print_error("Failed to allocate memory for ddl log free list");
 
660
      return(true);
 
661
    }
 
662
    global_ddl_log.num_entries++;
 
663
    used_entry->entry_pos= global_ddl_log.num_entries;
 
664
    *write_header= true;
 
665
  }
 
666
  else
 
667
  {
 
668
    used_entry= global_ddl_log.first_free;
 
669
    global_ddl_log.first_free= used_entry->next_log_entry;
 
670
    *write_header= false;
 
671
  }
 
672
  /*
 
673
    Move from free list to used list
 
674
  */
 
675
  used_entry->next_log_entry= first_used;
 
676
  used_entry->prev_log_entry= NULL;
 
677
  global_ddl_log.first_used= used_entry;
 
678
  if (first_used)
 
679
    first_used->prev_log_entry= used_entry;
 
680
 
 
681
  *active_entry= used_entry;
 
682
  return(false);
 
683
}
 
684
 
 
685
 
 
686
/*
 
687
  External interface methods for the DDL log Module
 
688
  ---------------------------------------------------
 
689
*/
 
690
 
 
691
/*
 
692
  SYNOPSIS
 
693
    write_ddl_log_entry()
 
694
    ddl_log_entry         Information about log entry
 
695
    out:entry_written     Entry information written into   
 
696
 
 
697
  RETURN VALUES
 
698
    true                      Error
 
699
    false                     Success
 
700
 
 
701
  DESCRIPTION
 
702
    A careful write of the ddl log is performed to ensure that we can
 
703
    handle crashes occurring during CREATE and ALTER TABLE processing.
 
704
*/
 
705
 
 
706
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
 
707
                         DDL_LOG_MEMORY_ENTRY **active_entry)
 
708
{
 
709
  bool error, write_header;
 
710
 
 
711
  if (init_ddl_log())
 
712
  {
 
713
    return(true);
 
714
  }
 
715
  global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
 
716
                                    (char)DDL_LOG_ENTRY_CODE;
 
717
  global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
 
718
                                    (char)ddl_log_entry->action_type;
 
719
  global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
 
720
  int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
 
721
            ddl_log_entry->next_entry);
 
722
  assert(strlen(ddl_log_entry->name) < FN_LEN);
 
723
  strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
 
724
          ddl_log_entry->name, FN_LEN - 1);
 
725
  if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
 
726
      ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
 
727
  {
 
728
    assert(strlen(ddl_log_entry->from_name) < FN_LEN);
 
729
    strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
 
730
          ddl_log_entry->from_name, FN_LEN - 1);
 
731
  }
 
732
  else
 
733
    global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
 
734
  assert(strlen(ddl_log_entry->handler_name) < FN_LEN);
 
735
  strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
 
736
          ddl_log_entry->handler_name, FN_LEN - 1);
 
737
  if (get_free_ddl_log_entry(active_entry, &write_header))
 
738
  {
 
739
    return(true);
 
740
  }
 
741
  error= false;
 
742
  if (write_ddl_log_file_entry((*active_entry)->entry_pos))
 
743
  {
 
744
    error= true;
 
745
    sql_print_error("Failed to write entry_no = %u",
 
746
                    (*active_entry)->entry_pos);
 
747
  }
 
748
  if (write_header && !error)
 
749
  {
 
750
    VOID(sync_ddl_log());
 
751
    if (write_ddl_log_header())
 
752
      error= true;
 
753
  }
 
754
  if (error)
 
755
    release_ddl_log_memory_entry(*active_entry);
 
756
  return(error);
 
757
}
 
758
 
 
759
 
 
760
/*
 
761
  Write final entry in the ddl log
 
762
  SYNOPSIS
 
763
    write_execute_ddl_log_entry()
 
764
    first_entry                    First entry in linked list of entries
 
765
                                   to execute, if 0 = NULL it means that
 
766
                                   the entry is removed and the entries
 
767
                                   are put into the free list.
 
768
    complete                       Flag indicating we are simply writing
 
769
                                   info about that entry has been completed
 
770
    in:out:active_entry            Entry to execute, 0 = NULL if the entry
 
771
                                   is written first time and needs to be
 
772
                                   returned. In this case the entry written
 
773
                                   is returned in this parameter
 
774
  RETURN VALUES
 
775
    true                           Error
 
776
    false                          Success
 
777
 
 
778
  DESCRIPTION
 
779
    This is the last write in the ddl log. The previous log entries have
 
780
    already been written but not yet synched to disk.
 
781
    We write a couple of log entries that describes action to perform.
 
782
    This entries are set-up in a linked list, however only when a first
 
783
    execute entry is put as the first entry these will be executed.
 
784
    This routine writes this first 
 
785
*/ 
 
786
 
 
787
bool write_execute_ddl_log_entry(uint first_entry,
 
788
                                 bool complete,
 
789
                                 DDL_LOG_MEMORY_ENTRY **active_entry)
 
790
{
 
791
  bool write_header= false;
 
792
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
793
 
 
794
  if (init_ddl_log())
 
795
  {
 
796
    return(true);
 
797
  }
 
798
  if (!complete)
 
799
  {
 
800
    /*
 
801
      We haven't synched the log entries yet, we synch them now before
 
802
      writing the execute entry. If complete is true we haven't written
 
803
      any log entries before, we are only here to write the execute
 
804
      entry to indicate it is done.
 
805
    */
 
806
    VOID(sync_ddl_log());
 
807
    file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
 
808
  }
 
809
  else
 
810
    file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
 
811
  file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
 
812
  file_entry_buf[DDL_LOG_PHASE_POS]= 0;
 
813
  int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
 
814
  file_entry_buf[DDL_LOG_NAME_POS]= 0;
 
815
  file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
 
816
  file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
 
817
  if (!(*active_entry))
 
818
  {
 
819
    if (get_free_ddl_log_entry(active_entry, &write_header))
 
820
    {
 
821
      return(true);
 
822
    }
 
823
  }
 
824
  if (write_ddl_log_file_entry((*active_entry)->entry_pos))
 
825
  {
 
826
    sql_print_error("Error writing execute entry in ddl log");
 
827
    release_ddl_log_memory_entry(*active_entry);
 
828
    return(true);
 
829
  }
 
830
  VOID(sync_ddl_log());
 
831
  if (write_header)
 
832
  {
 
833
    if (write_ddl_log_header())
 
834
    {
 
835
      release_ddl_log_memory_entry(*active_entry);
 
836
      return(true);
 
837
    }
 
838
  }
 
839
  return(false);
 
840
}
 
841
 
 
842
 
 
843
/*
 
844
  For complex rename operations we need to deactivate individual entries.
 
845
  SYNOPSIS
 
846
    deactivate_ddl_log_entry()
 
847
    entry_no                      Entry position of record to change
 
848
  RETURN VALUES
 
849
    true                         Error
 
850
    false                        Success
 
851
  DESCRIPTION
 
852
    During replace operations where we start with an existing table called
 
853
    t1 and a replacement table called t1#temp or something else and where
 
854
    we want to delete t1 and rename t1#temp to t1 this is not possible to
 
855
    do in a safe manner unless the ddl log is informed of the phases in
 
856
    the change.
 
857
 
 
858
    Delete actions are 1-phase actions that can be ignored immediately after
 
859
    being executed.
 
860
    Rename actions from x to y is also a 1-phase action since there is no
 
861
    interaction with any other handlers named x and y.
 
862
    Replace action where drop y and x -> y happens needs to be a two-phase
 
863
    action. Thus the first phase will drop y and the second phase will
 
864
    rename x -> y.
 
865
*/
 
866
 
 
867
bool deactivate_ddl_log_entry(uint entry_no)
 
868
{
 
869
  char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
 
870
 
 
871
  if (!read_ddl_log_file_entry(entry_no))
 
872
  {
 
873
    if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
 
874
    {
 
875
      if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
 
876
          file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
 
877
          (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
 
878
           file_entry_buf[DDL_LOG_PHASE_POS] == 1))
 
879
        file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
 
880
      else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
 
881
      {
 
882
        assert(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
 
883
        file_entry_buf[DDL_LOG_PHASE_POS]= 1;
 
884
      }
 
885
      else
 
886
      {
 
887
        assert(0);
 
888
      }
 
889
      if (write_ddl_log_file_entry(entry_no))
 
890
      {
 
891
        sql_print_error("Error in deactivating log entry. Position = %u",
 
892
                        entry_no);
 
893
        return(true);
 
894
      }
 
895
    }
 
896
  }
 
897
  else
 
898
  {
 
899
    sql_print_error("Failed in reading entry before deactivating it");
 
900
    return(true);
 
901
  }
 
902
  return(false);
 
903
}
 
904
 
 
905
 
 
906
/*
 
907
  Sync ddl log file
 
908
  SYNOPSIS
 
909
    sync_ddl_log()
 
910
  RETURN VALUES
 
911
    true                      Error
 
912
    false                     Success
 
913
*/
 
914
 
 
915
bool sync_ddl_log()
 
916
{
 
917
  bool error= false;
 
918
 
 
919
  if ((!global_ddl_log.recovery_phase) &&
 
920
      init_ddl_log())
 
921
  {
 
922
    return(true);
 
923
  }
 
924
  if (my_sync(global_ddl_log.file_id, MYF(0)))
 
925
  {
 
926
    /* Write to error log */
 
927
    sql_print_error("Failed to sync ddl log");
 
928
    error= true;
 
929
  }
 
930
  return(error);
 
931
}
 
932
 
 
933
 
 
934
/*
 
935
  Release a log memory entry
 
936
  SYNOPSIS
 
937
    release_ddl_log_memory_entry()
 
938
    log_memory_entry                Log memory entry to release
 
939
  RETURN VALUES
 
940
    NONE
 
941
*/
 
942
 
 
943
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
 
944
{
 
945
  DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
 
946
  DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
 
947
  DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
 
948
 
 
949
  global_ddl_log.first_free= log_entry;
 
950
  log_entry->next_log_entry= first_free;
 
951
 
 
952
  if (prev_log_entry)
 
953
    prev_log_entry->next_log_entry= next_log_entry;
 
954
  else
 
955
    global_ddl_log.first_used= next_log_entry;
 
956
  if (next_log_entry)
 
957
    next_log_entry->prev_log_entry= prev_log_entry;
 
958
  return;
 
959
}
 
960
 
 
961
 
 
962
/*
 
963
  Execute one entry in the ddl log. Executing an entry means executing
 
964
  a linked list of actions.
 
965
  SYNOPSIS
 
966
    execute_ddl_log_entry()
 
967
    first_entry                Reference to first action in entry
 
968
  RETURN VALUES
 
969
    true                       Error
 
970
    false                      Success
 
971
*/
 
972
 
 
973
bool execute_ddl_log_entry(THD *thd, uint first_entry)
 
974
{
 
975
  DDL_LOG_ENTRY ddl_log_entry;
 
976
  uint read_entry= first_entry;
 
977
 
 
978
  pthread_mutex_lock(&LOCK_gdl);
 
979
  do
 
980
  {
 
981
    if (read_ddl_log_entry(read_entry, &ddl_log_entry))
 
982
    {
 
983
      /* Write to error log and continue with next log entry */
 
984
      sql_print_error("Failed to read entry = %u from ddl log",
 
985
                      read_entry);
 
986
      break;
 
987
    }
 
988
    assert(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
 
989
                ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
 
990
 
 
991
    if (execute_ddl_log_action(thd, &ddl_log_entry))
 
992
    {
 
993
      /* Write to error log and continue with next log entry */
 
994
      sql_print_error("Failed to execute action for entry = %u from ddl log",
 
995
                      read_entry);
 
996
      break;
 
997
    }
 
998
    read_entry= ddl_log_entry.next_entry;
 
999
  } while (read_entry);
 
1000
  pthread_mutex_unlock(&LOCK_gdl);
 
1001
  return(false);
 
1002
}
 
1003
 
 
1004
 
 
1005
/*
 
1006
  Close the ddl log
 
1007
  SYNOPSIS
 
1008
    close_ddl_log()
 
1009
  RETURN VALUES
 
1010
    NONE
 
1011
*/
 
1012
 
 
1013
static void close_ddl_log()
 
1014
{
 
1015
  if (global_ddl_log.file_id >= 0)
 
1016
  {
 
1017
    VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
 
1018
    global_ddl_log.file_id= (File) -1;
 
1019
  }
 
1020
  return;
 
1021
}
 
1022
 
 
1023
 
 
1024
/*
 
1025
  Execute the ddl log at recovery of MySQL Server
 
1026
  SYNOPSIS
 
1027
    execute_ddl_log_recovery()
 
1028
  RETURN VALUES
 
1029
    NONE
 
1030
*/
 
1031
 
 
1032
void execute_ddl_log_recovery()
 
1033
{
 
1034
  uint num_entries, i;
 
1035
  THD *thd;
 
1036
  DDL_LOG_ENTRY ddl_log_entry;
 
1037
  char file_name[FN_REFLEN];
 
1038
 
 
1039
  /*
 
1040
    Initialise global_ddl_log struct
 
1041
  */
 
1042
  bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
 
1043
  global_ddl_log.inited= false;
 
1044
  global_ddl_log.recovery_phase= true;
 
1045
  global_ddl_log.io_size= IO_SIZE;
 
1046
  global_ddl_log.file_id= (File) -1;
 
1047
 
 
1048
  /*
 
1049
    To be able to run this from boot, we allocate a temporary THD
 
1050
  */
 
1051
  if (!(thd=new THD))
 
1052
    return;
 
1053
  thd->thread_stack= (char*) &thd;
 
1054
  thd->store_globals();
 
1055
 
 
1056
  num_entries= read_ddl_log_header();
 
1057
  for (i= 1; i < num_entries + 1; i++)
 
1058
  {
 
1059
    if (read_ddl_log_entry(i, &ddl_log_entry))
 
1060
    {
 
1061
      sql_print_error("Failed to read entry no = %u from ddl log",
 
1062
                       i);
 
1063
      continue;
 
1064
    }
 
1065
    if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
 
1066
    {
 
1067
      if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
 
1068
      {
 
1069
        /* Real unpleasant scenario but we continue anyways.  */
 
1070
        continue;
 
1071
      }
 
1072
    }
 
1073
  }
 
1074
  close_ddl_log();
 
1075
  create_ddl_log_file_name(file_name);
 
1076
  VOID(my_delete(file_name, MYF(0)));
 
1077
  global_ddl_log.recovery_phase= false;
 
1078
  delete thd;
 
1079
  /* Remember that we don't have a THD */
 
1080
  my_pthread_setspecific_ptr(THR_THD,  0);
 
1081
  return;
 
1082
}
 
1083
 
 
1084
 
 
1085
/*
 
1086
  Release all memory allocated to the ddl log
 
1087
  SYNOPSIS
 
1088
    release_ddl_log()
 
1089
  RETURN VALUES
 
1090
    NONE
 
1091
*/
 
1092
 
 
1093
void release_ddl_log()
 
1094
{
 
1095
  DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
 
1096
  DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
 
1097
 
 
1098
  if (!global_ddl_log.do_release)
 
1099
    return;
 
1100
 
 
1101
  pthread_mutex_lock(&LOCK_gdl);
 
1102
  while (used_list)
 
1103
  {
 
1104
    DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
 
1105
    my_free(used_list, MYF(0));
 
1106
    used_list= tmp;
 
1107
  }
 
1108
  while (free_list)
 
1109
  {
 
1110
    DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
 
1111
    my_free(free_list, MYF(0));
 
1112
    free_list= tmp;
 
1113
  }
 
1114
  close_ddl_log();
 
1115
  global_ddl_log.inited= 0;
 
1116
  pthread_mutex_unlock(&LOCK_gdl);
 
1117
  VOID(pthread_mutex_destroy(&LOCK_gdl));
 
1118
  global_ddl_log.do_release= false;
 
1119
  return;
 
1120
}
 
1121
 
 
1122
 
 
1123
/*
 
1124
---------------------------------------------------------------------------
 
1125
 
 
1126
  END MODULE DDL log
 
1127
  --------------------
 
1128
 
 
1129
---------------------------------------------------------------------------
 
1130
*/
 
1131
 
92
1132
 
93
1133
/*
94
1134
  SYNOPSIS
95
1135
    write_bin_log()
96
 
    session                           Thread object
 
1136
    thd                           Thread object
 
1137
    clear_error                   is clear_error to be called
97
1138
    query                         Query to log
98
1139
    query_length                  Length of query
99
1140
 
102
1143
 
103
1144
  DESCRIPTION
104
1145
    Write the binlog if open, routine used in multiple places in this
105
 
    cursor
106
 
*/
107
 
 
108
 
void write_bin_log(Session *session, const std::string &query)
109
 
{
110
 
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(*session, query);
 
1146
    file
 
1147
*/
 
1148
 
 
1149
void write_bin_log(THD *thd, bool clear_error,
 
1150
                   char const *query, ulong query_length)
 
1151
{
 
1152
  if (mysql_bin_log.is_open())
 
1153
  {
 
1154
    if (clear_error)
 
1155
      thd->clear_error();
 
1156
    thd->binlog_query(THD::STMT_QUERY_TYPE,
 
1157
                      query, query_length, false, false);
 
1158
  }
 
1159
}
 
1160
 
 
1161
 
 
1162
/*
 
1163
 delete (drop) tables.
 
1164
 
 
1165
  SYNOPSIS
 
1166
   mysql_rm_table()
 
1167
   thd                  Thread handle
 
1168
   tables               List of tables to delete
 
1169
   if_exists            If 1, don't give error if one table doesn't exists
 
1170
 
 
1171
  NOTES
 
1172
    Will delete all tables that can be deleted and give a compact error
 
1173
    messages for tables that could not be deleted.
 
1174
    If a table is in use, we will wait for all users to free the table
 
1175
    before dropping it
 
1176
 
 
1177
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
 
1178
    not if under LOCK TABLES.
 
1179
 
 
1180
  RETURN
 
1181
    false OK.  In this case ok packet is sent to user
 
1182
    true  Error
 
1183
 
 
1184
*/
 
1185
 
 
1186
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
 
1187
                    my_bool drop_temporary)
 
1188
{
 
1189
  bool error, need_start_waiting= false;
 
1190
 
 
1191
  if (tables && tables->schema_table)
 
1192
  {
 
1193
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
1194
    return(true);
 
1195
  }
 
1196
 
 
1197
  /* mark for close and remove all cached entries */
 
1198
 
 
1199
  if (!drop_temporary)
 
1200
  {
 
1201
    if (!thd->locked_tables &&
 
1202
        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
 
1203
      return(true);
 
1204
  }
 
1205
 
 
1206
  /*
 
1207
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
 
1208
    LOCK_open during wait_if_global_read_lock(), other threads could not
 
1209
    close their tables. This would make a pretty deadlock.
 
1210
  */
 
1211
  error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
 
1212
 
 
1213
  if (need_start_waiting)
 
1214
    start_waiting_global_read_lock(thd);
 
1215
 
 
1216
  if (error)
 
1217
    return(true);
 
1218
  my_ok(thd);
 
1219
  return(false);
112
1220
}
113
1221
 
114
1222
/*
115
1223
  Execute the drop of a normal or temporary table
116
1224
 
117
1225
  SYNOPSIS
118
 
    rm_table_part2()
119
 
    session                     Thread Cursor
 
1226
    mysql_rm_table_part2()
 
1227
    thd                 Thread handler
120
1228
    tables              Tables to drop
121
1229
    if_exists           If set, don't give an error if table doesn't exists.
122
1230
                        In this case we give an warning of level 'NOTE'
123
1231
    drop_temporary      Only drop temporary tables
 
1232
    drop_view           Allow to delete VIEW .frm
 
1233
    dont_log_query      Don't write query to log files. This will also not
 
1234
                        generate warnings if the handler files doesn't exists  
124
1235
 
125
 
  @todo
 
1236
  TODO:
126
1237
    When logging to the binary log, we should log
127
1238
    tmp_tables and transactional tables as separate statements if we
128
1239
    are in a transaction;  This is needed to get these tables into the
138
1249
   -1   Thread was killed
139
1250
*/
140
1251
 
141
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
 
                   bool drop_temporary)
 
1252
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
 
1253
                         bool drop_temporary, bool drop_view,
 
1254
                         bool dont_log_query)
143
1255
{
144
 
  TableList *table;
145
 
  util::string::vector wrong_tables;
 
1256
  TABLE_LIST *table;
 
1257
  char path[FN_REFLEN], *alias;
 
1258
  uint path_length;
 
1259
  String wrong_tables;
146
1260
  int error= 0;
147
 
  bool foreign_key_error= false;
148
 
 
149
 
  do
150
 
  {
151
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
152
 
 
153
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
154
 
    {
155
 
      return 1;
156
 
    }
157
 
 
158
 
    /* Don't give warnings for not found errors, as we already generate notes */
159
 
    session->no_warnings_for_error= 1;
160
 
 
161
 
    for (table= tables; table; table= table->next_local)
162
 
    {
163
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
164
 
 
165
 
      error= session->drop_temporary_table(tmp_identifier);
166
 
 
167
 
      switch (error) {
168
 
      case  0:
169
 
        // removed temporary table
170
 
        continue;
171
 
      case -1:
 
1261
  int non_temp_tables_count= 0;
 
1262
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
 
1263
  String built_query;
 
1264
 
 
1265
  if (thd->current_stmt_binlog_row_based && !dont_log_query)
 
1266
  {
 
1267
    built_query.set_charset(system_charset_info);
 
1268
    if (if_exists)
 
1269
      built_query.append("DROP TABLE IF EXISTS ");
 
1270
    else
 
1271
      built_query.append("DROP TABLE ");
 
1272
  }
 
1273
 
 
1274
  mysql_ha_rm_tables(thd, tables, false);
 
1275
 
 
1276
  pthread_mutex_lock(&LOCK_open);
 
1277
 
 
1278
  /*
 
1279
    If we have the table in the definition cache, we don't have to check the
 
1280
    .frm file to find if the table is a normal table (not view) and what
 
1281
    engine to use.
 
1282
  */
 
1283
 
 
1284
  for (table= tables; table; table= table->next_local)
 
1285
  {
 
1286
    TABLE_SHARE *share;
 
1287
    table->db_type= NULL;
 
1288
    if ((share= get_cached_table_share(table->db, table->table_name)))
 
1289
      table->db_type= share->db_type();
 
1290
  }
 
1291
 
 
1292
  if (!drop_temporary && lock_table_names_exclusively(thd, tables))
 
1293
  {
 
1294
    pthread_mutex_unlock(&LOCK_open);
 
1295
    return(1);
 
1296
  }
 
1297
 
 
1298
  /* Don't give warnings for not found errors, as we already generate notes */
 
1299
  thd->no_warnings_for_error= 1;
 
1300
 
 
1301
  for (table= tables; table; table= table->next_local)
 
1302
  {
 
1303
    char *db=table->db;
 
1304
    handlerton *table_type;
 
1305
    enum legacy_db_type frm_db_type;
 
1306
 
 
1307
 
 
1308
    error= drop_temporary_table(thd, table);
 
1309
 
 
1310
    switch (error) {
 
1311
    case  0:
 
1312
      // removed temporary table
 
1313
      tmp_table_deleted= 1;
 
1314
      continue;
 
1315
    case -1:
 
1316
      assert(thd->in_sub_stmt);
 
1317
      error= 1;
 
1318
      goto err_with_placeholders;
 
1319
    default:
 
1320
      // temporary table not found
 
1321
      error= 0;
 
1322
    }
 
1323
 
 
1324
    /*
 
1325
      If row-based replication is used and the table is not a
 
1326
      temporary table, we add the table name to the drop statement
 
1327
      being built.  The string always end in a comma and the comma
 
1328
      will be chopped off before being written to the binary log.
 
1329
      */
 
1330
    if (thd->current_stmt_binlog_row_based && !dont_log_query)
 
1331
    {
 
1332
      non_temp_tables_count++;
 
1333
      /*
 
1334
        Don't write the database name if it is the current one (or if
 
1335
        thd->db is NULL).
 
1336
      */
 
1337
      built_query.append("`");
 
1338
      if (thd->db == NULL || strcmp(db,thd->db) != 0)
 
1339
      {
 
1340
        built_query.append(db);
 
1341
        built_query.append("`.`");
 
1342
      }
 
1343
 
 
1344
      built_query.append(table->table_name);
 
1345
      built_query.append("`,");
 
1346
    }
 
1347
 
 
1348
    table_type= table->db_type;
 
1349
    if (!drop_temporary)
 
1350
    {
 
1351
      TABLE *locked_table;
 
1352
      abort_locked_tables(thd, db, table->table_name);
 
1353
      remove_table_from_cache(thd, db, table->table_name,
 
1354
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
1355
                              RTFC_CHECK_KILLED_FLAG);
 
1356
      /*
 
1357
        If the table was used in lock tables, remember it so that
 
1358
        unlock_table_names can free it
 
1359
      */
 
1360
      if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
 
1361
        table->table= locked_table;
 
1362
 
 
1363
      if (thd->killed)
 
1364
      {
 
1365
        error= -1;
 
1366
        goto err_with_placeholders;
 
1367
      }
 
1368
      alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
 
1369
      /* remove .frm file and engine files */
 
1370
      path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
1371
                                        table->internal_tmp_table ?
 
1372
                                        FN_IS_TMP : 0);
 
1373
    }
 
1374
    if (drop_temporary ||
 
1375
        ((table_type == NULL && (access(path, F_OK) && ha_create_table_from_engine(thd, db, alias))) ||
 
1376
         (!drop_view && mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
 
1377
    {
 
1378
      // Table was not found on disk and table can't be created from engine
 
1379
      if (if_exists)
 
1380
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
1381
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
1382
                            table->table_name);
 
1383
      else
172
1384
        error= 1;
173
 
        break;
174
 
      default:
175
 
        // temporary table not found
176
 
        error= 0;
177
 
      }
178
 
 
179
 
      if (drop_temporary == false)
180
 
      {
181
 
        Table *locked_table;
182
 
        abort_locked_tables(session, tmp_identifier);
183
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
184
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
185
 
                                              RTFC_CHECK_KILLED_FLAG);
186
 
        /*
187
 
          If the table was used in lock tables, remember it so that
188
 
          unlock_table_names can free it
189
 
        */
190
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
191
 
          table->table= locked_table;
192
 
 
193
 
        if (session->getKilled())
194
 
        {
195
 
          error= -1;
196
 
          break;
197
 
        }
198
 
      }
199
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
200
 
 
201
 
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
202
 
 
203
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
 
      {
205
 
        // Table was not found on disk and table can't be created from engine
206
 
        if (if_exists)
207
 
        {
208
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
 
                              table->getTableName());
211
 
        }
212
 
        else
213
 
        {
214
 
          error= 1;
215
 
        }
216
 
      }
217
 
      else
218
 
      {
219
 
        drizzled::error_t local_error;
220
 
 
221
 
        /* Generate transaction event ONLY when we successfully drop */ 
222
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
223
 
        {
224
 
          if (message) // If we have no definition, we don't know if the table should have been replicated
225
 
          {
226
 
            TransactionServices &transaction_services= TransactionServices::singleton();
227
 
            transaction_services.dropTable(*session, identifier, *message, if_exists);
228
 
          }
229
 
        }
230
 
        else
231
 
        {
232
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
233
 
          {
234
 
            error= 0;
235
 
            session->clear_error();
236
 
          }
237
 
 
238
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
239
 
          {
240
 
            /* the table is referenced by a foreign key constraint */
241
 
            foreign_key_error= true;
242
 
          }
243
 
          error= local_error;
244
 
        }
245
 
      }
246
 
 
247
 
      if (error)
248
 
      {
249
 
        wrong_tables.push_back(table->getTableName());
250
 
      }
251
 
    }
252
 
 
253
 
    tables->unlock_table_names();
254
 
 
255
 
  } while (0);
256
 
 
257
 
  if (wrong_tables.size())
 
1385
    }
 
1386
    else
 
1387
    {
 
1388
      char *end;
 
1389
      if (table_type == NULL)
 
1390
      {
 
1391
        mysql_frm_type(thd, path, &frm_db_type);
 
1392
        table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
 
1393
      }
 
1394
      // Remove extension for delete
 
1395
      *(end= path + path_length - reg_ext_length)= '\0';
 
1396
      error= ha_delete_table(thd, table_type, path, db, table->table_name,
 
1397
                             !dont_log_query);
 
1398
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && 
 
1399
          (if_exists || table_type == NULL))
 
1400
      {
 
1401
        error= 0;
 
1402
        thd->clear_error();
 
1403
      }
 
1404
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
1405
      {
 
1406
        /* the table is referenced by a foreign key constraint */
 
1407
        foreign_key_error=1;
 
1408
      }
 
1409
      if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
 
1410
      {
 
1411
        int new_error;
 
1412
        /* Delete the table definition file */
 
1413
        strmov(end,reg_ext);
 
1414
        if (!(new_error=my_delete(path,MYF(MY_WME))))
 
1415
        {
 
1416
          some_tables_deleted=1;
 
1417
          new_error= 0;
 
1418
        }
 
1419
        error|= new_error;
 
1420
      }
 
1421
    }
 
1422
    if (error)
 
1423
    {
 
1424
      if (wrong_tables.length())
 
1425
        wrong_tables.append(',');
 
1426
      wrong_tables.append(String(table->table_name,system_charset_info));
 
1427
    }
 
1428
  }
 
1429
  /*
 
1430
    It's safe to unlock LOCK_open: we have an exclusive lock
 
1431
    on the table name.
 
1432
  */
 
1433
  pthread_mutex_unlock(&LOCK_open);
 
1434
  thd->thread_specific_used|= tmp_table_deleted;
 
1435
  error= 0;
 
1436
  if (wrong_tables.length())
258
1437
  {
259
 
    if (not foreign_key_error)
260
 
    {
261
 
      std::string table_error;
262
 
 
263
 
      for (util::string::vector::iterator iter= wrong_tables.begin();
264
 
           iter != wrong_tables.end();
265
 
           iter++)
266
 
      {
267
 
        table_error+= *iter;
268
 
        table_error+= ',';
269
 
      }
270
 
      table_error.resize(table_error.size() -1);
271
 
 
 
1438
    if (!foreign_key_error)
272
1439
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
 
                      table_error.c_str());
274
 
    }
 
1440
                      wrong_tables.c_ptr());
275
1441
    else
276
 
    {
277
1442
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
 
1443
    error= 1;
 
1444
  }
 
1445
 
 
1446
  if (some_tables_deleted || tmp_table_deleted || !error)
 
1447
  {
 
1448
    if (!dont_log_query)
 
1449
    {
 
1450
      if (!thd->current_stmt_binlog_row_based ||
 
1451
          (non_temp_tables_count > 0 && !tmp_table_deleted))
 
1452
      {
 
1453
        /*
 
1454
          In this case, we are either using statement-based
 
1455
          replication or using row-based replication but have only
 
1456
          deleted one or more non-temporary tables (and no temporary
 
1457
          tables).  In this case, we can write the original query into
 
1458
          the binary log.
 
1459
         */
 
1460
        write_bin_log(thd, !error, thd->query, thd->query_length);
 
1461
      }
 
1462
      else if (thd->current_stmt_binlog_row_based &&
 
1463
               non_temp_tables_count > 0 &&
 
1464
               tmp_table_deleted)
 
1465
      {
 
1466
        /*
 
1467
          In this case we have deleted both temporary and
 
1468
          non-temporary tables, so:
 
1469
          - since we have deleted a non-temporary table we have to
 
1470
            binlog the statement, but
 
1471
          - since we have deleted a temporary table we cannot binlog
 
1472
            the statement (since the table has not been created on the
 
1473
            slave, this might cause the slave to stop).
 
1474
 
 
1475
          Instead, we write a built statement, only containing the
 
1476
          non-temporary tables, to the binary log
 
1477
        */
 
1478
        built_query.chop();                  // Chop of the last comma
 
1479
        built_query.append(" /* generated by server */");
 
1480
        write_bin_log(thd, !error, built_query.ptr(), built_query.length());
 
1481
      }
 
1482
      /*
 
1483
        The remaining cases are:
 
1484
        - no tables where deleted and
 
1485
        - only temporary tables where deleted and row-based
 
1486
          replication is used.
 
1487
        In both these cases, nothing should be written to the binary
 
1488
        log.
 
1489
      */
278
1490
    }
279
 
    error= 1;
280
1491
  }
281
 
 
282
 
  session->no_warnings_for_error= 0;
283
 
 
284
 
  return error;
 
1492
  pthread_mutex_lock(&LOCK_open);
 
1493
err_with_placeholders:
 
1494
  unlock_table_names(thd, tables, (TABLE_LIST*) 0);
 
1495
  pthread_mutex_unlock(&LOCK_open);
 
1496
  thd->no_warnings_for_error= 0;
 
1497
  return(error);
 
1498
}
 
1499
 
 
1500
 
 
1501
/*
 
1502
  Quickly remove a table.
 
1503
 
 
1504
  SYNOPSIS
 
1505
    quick_rm_table()
 
1506
      base                      The handlerton handle.
 
1507
      db                        The database name.
 
1508
      table_name                The table name.
 
1509
      flags                     flags for build_table_filename().
 
1510
 
 
1511
  RETURN
 
1512
    0           OK
 
1513
    != 0        Error
 
1514
*/
 
1515
 
 
1516
bool quick_rm_table(handlerton *base,const char *db,
 
1517
                    const char *table_name, uint flags)
 
1518
{
 
1519
  char path[FN_REFLEN];
 
1520
  bool error= 0;
 
1521
 
 
1522
  uint path_length= build_table_filename(path, sizeof(path),
 
1523
                                         db, table_name, reg_ext, flags);
 
1524
  if (my_delete(path,MYF(0)))
 
1525
    error= 1; /* purecov: inspected */
 
1526
  path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
 
1527
  return(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
 
1528
              error);
285
1529
}
286
1530
 
287
1531
/*
297
1541
  PRIMARY keys are prioritized.
298
1542
*/
299
1543
 
300
 
static int sort_keys(KeyInfo *a, KeyInfo *b)
 
1544
static int sort_keys(KEY *a, KEY *b)
301
1545
{
302
1546
  ulong a_flags= a->flags, b_flags= b->flags;
303
 
 
 
1547
  
304
1548
  if (a_flags & HA_NOSAME)
305
1549
  {
306
1550
    if (!(b_flags & HA_NOSAME))
310
1554
      /* Sort NOT NULL keys before other keys */
311
1555
      return (a_flags & (HA_NULL_PART_KEY)) ? 1 : -1;
312
1556
    }
313
 
    if (is_primary_key(a))
 
1557
    if (a->name == primary_key_name)
314
1558
      return -1;
315
 
    if (is_primary_key(b))
 
1559
    if (b->name == primary_key_name)
316
1560
      return 1;
317
1561
    /* Sort keys don't containing partial segments before others */
318
1562
    if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
349
1593
    1             Error
350
1594
*/
351
1595
 
352
 
class typelib_set_member
353
 
{
354
 
public:
355
 
  string s;
356
 
  const CHARSET_INFO * const cs;
357
 
 
358
 
  typelib_set_member(const char* value, unsigned int length,
359
 
                     const CHARSET_INFO * const charset)
360
 
    : s(value, length),
361
 
      cs(charset)
362
 
  {}
363
 
};
364
 
 
365
 
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
366
 
{
367
 
  return (my_strnncoll(a.cs,
368
 
                       (const unsigned char*)a.s.c_str(), a.s.length(),
369
 
                       (const unsigned char*)b.s.c_str(), b.s.length())==0);
370
 
}
371
 
 
372
 
 
373
 
namespace
374
 
{
375
 
class typelib_set_member_hasher
376
 
{
377
 
  boost::hash<string> hasher;
378
 
public:
379
 
  std::size_t operator()(const typelib_set_member& t) const
380
 
  {
381
 
    return hasher(t.s);
382
 
  }
383
 
};
384
 
}
385
 
 
386
 
static bool check_duplicates_in_interval(const char *set_or_name,
387
 
                                         const char *name, TYPELIB *typelib,
388
 
                                         const CHARSET_INFO * const cs,
389
 
                                         unsigned int *dup_val_count)
 
1596
bool check_duplicates_in_interval(const char *set_or_name,
 
1597
                                  const char *name, TYPELIB *typelib,
 
1598
                                  CHARSET_INFO *cs, unsigned int *dup_val_count)
390
1599
{
391
1600
  TYPELIB tmp= *typelib;
392
1601
  const char **cur_value= typelib->type_names;
393
1602
  unsigned int *cur_length= typelib->type_lengths;
394
 
  *dup_val_count= 0;
395
 
 
396
 
  boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
397
 
 
398
 
  for ( ; tmp.count > 0; cur_value++, cur_length++)
 
1603
  *dup_val_count= 0;  
 
1604
  
 
1605
  for ( ; tmp.count > 1; cur_value++, cur_length++)
399
1606
  {
400
1607
    tmp.type_names++;
401
1608
    tmp.type_lengths++;
402
1609
    tmp.count--;
403
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
1610
    if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
404
1611
    {
405
1612
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
406
1613
               name,*cur_value,set_or_name);
407
1614
      return 1;
408
1615
    }
409
 
    else
410
 
      interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
411
1616
  }
412
1617
  return 0;
413
1618
}
431
1636
  RETURN VALUES
432
1637
    void
433
1638
*/
434
 
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
435
 
                                       TYPELIB *interval,
436
 
                                       uint32_t *max_length,
437
 
                                       uint32_t *tot_length)
 
1639
void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
 
1640
                                uint32 *max_length, uint32 *tot_length)
438
1641
{
439
1642
  const char **pos;
440
 
  uint32_t *len;
 
1643
  uint *len;
441
1644
  *max_length= *tot_length= 0;
442
1645
  for (pos= interval->type_names, len= interval->type_lengths;
443
1646
       *pos ; pos++, len++)
444
1647
  {
445
 
    uint32_t length= cs->cset->numchars(cs, *pos, *pos + *len);
 
1648
    uint length= cs->cset->numchars(cs, *pos, *pos + *len);
446
1649
    *tot_length+= length;
447
 
    set_if_bigger(*max_length, (uint32_t)length);
 
1650
    set_if_bigger(*max_length, (uint32)length);
448
1651
  }
449
1652
}
450
1653
 
 
1654
 
451
1655
/*
452
1656
  Prepare a create_table instance for packing
453
1657
 
456
1660
    sql_field     field to prepare for packing
457
1661
    blob_columns  count for BLOBs
458
1662
    timestamps    count for timestamps
 
1663
    table_flags   table flags
459
1664
 
460
1665
  DESCRIPTION
461
 
    This function prepares a CreateField instance.
 
1666
    This function prepares a Create_field instance.
462
1667
    Fields such as pack_flag are valid after this call.
463
1668
 
464
1669
  RETURN VALUES
465
1670
   0    ok
466
1671
   1    Error
467
1672
*/
468
 
int prepare_create_field(CreateField *sql_field,
469
 
                         uint32_t *blob_columns,
470
 
                         int *timestamps,
471
 
                         int *timestamps_with_niladic)
 
1673
 
 
1674
int prepare_create_field(Create_field *sql_field, 
 
1675
                         uint *blob_columns,
 
1676
                         int *timestamps, int *timestamps_with_niladic,
 
1677
                         int64_t table_flags __attribute__((__unused__)))
472
1678
{
473
1679
  unsigned int dup_val_count;
474
1680
 
479
1685
  assert(sql_field->charset);
480
1686
 
481
1687
  switch (sql_field->sql_type) {
482
 
  case DRIZZLE_TYPE_BLOB:
483
 
    sql_field->length= 8; // Unireg field length
 
1688
  case MYSQL_TYPE_BLOB:
 
1689
    sql_field->pack_flag=FIELDFLAG_BLOB |
 
1690
      pack_length_to_packflag(sql_field->pack_length -
 
1691
                              portable_sizeof_char_ptr);
 
1692
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1693
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1694
    sql_field->length=8;                        // Unireg field length
 
1695
    sql_field->unireg_check=Field::BLOB_FIELD;
484
1696
    (*blob_columns)++;
485
1697
    break;
486
 
 
487
 
  case DRIZZLE_TYPE_ENUM:
 
1698
  case MYSQL_TYPE_VARCHAR:
 
1699
  case MYSQL_TYPE_STRING:
 
1700
    sql_field->pack_flag=0;
 
1701
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1702
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1703
    break;
 
1704
  case MYSQL_TYPE_ENUM:
 
1705
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
1706
      FIELDFLAG_INTERVAL;
 
1707
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1708
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1709
    sql_field->unireg_check=Field::INTERVAL_FIELD;
 
1710
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
 
1711
                                 sql_field->interval,
 
1712
                                     sql_field->charset, &dup_val_count))
 
1713
      return(1);
 
1714
    break;
 
1715
  case MYSQL_TYPE_SET:
 
1716
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
 
1717
      FIELDFLAG_BITFIELD;
 
1718
    if (sql_field->charset->state & MY_CS_BINSORT)
 
1719
      sql_field->pack_flag|=FIELDFLAG_BINARY;
 
1720
    sql_field->unireg_check=Field::BIT_FIELD;
 
1721
    if (check_duplicates_in_interval("SET",sql_field->field_name,
 
1722
                                 sql_field->interval,
 
1723
                                     sql_field->charset, &dup_val_count))
 
1724
      return(1);
 
1725
    /* Check that count of unique members is not more then 64 */
 
1726
    if (sql_field->interval->count -  dup_val_count > sizeof(int64_t)*8)
488
1727
    {
489
 
      if (check_duplicates_in_interval("ENUM",
490
 
                                       sql_field->field_name,
491
 
                                       sql_field->interval,
492
 
                                       sql_field->charset,
493
 
                                       &dup_val_count))
494
 
      {
495
 
        return 1;
496
 
      }
 
1728
       my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
 
1729
       return(1);
497
1730
    }
498
1731
    break;
499
 
 
500
 
  case DRIZZLE_TYPE_MICROTIME:
501
 
  case DRIZZLE_TYPE_TIMESTAMP:
 
1732
  case MYSQL_TYPE_NEWDATE:  // Rest of string types
 
1733
  case MYSQL_TYPE_TIME:
 
1734
  case MYSQL_TYPE_DATETIME:
 
1735
  case MYSQL_TYPE_NULL:
 
1736
    sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
 
1737
    break;
 
1738
  case MYSQL_TYPE_NEWDECIMAL:
 
1739
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
1740
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
1741
                           FIELDFLAG_DECIMAL) |
 
1742
                          (sql_field->flags & ZEROFILL_FLAG ?
 
1743
                           FIELDFLAG_ZEROFILL : 0) |
 
1744
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
 
1745
    break;
 
1746
  case MYSQL_TYPE_TIMESTAMP:
502
1747
    /* We should replace old TIMESTAMP fields with their newer analogs */
503
1748
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
504
1749
    {
508
1753
        (*timestamps_with_niladic)++;
509
1754
      }
510
1755
      else
511
 
      {
512
1756
        sql_field->unireg_check= Field::NONE;
513
 
      }
514
1757
    }
515
1758
    else if (sql_field->unireg_check != Field::NONE)
516
 
    {
517
1759
      (*timestamps_with_niladic)++;
518
 
    }
519
1760
 
520
1761
    (*timestamps)++;
521
 
 
522
 
    break;
523
 
 
524
 
  case DRIZZLE_TYPE_BOOLEAN:
525
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
526
 
  case DRIZZLE_TYPE_DATETIME:
527
 
  case DRIZZLE_TYPE_DECIMAL:
528
 
  case DRIZZLE_TYPE_DOUBLE:
529
 
  case DRIZZLE_TYPE_LONG:
530
 
  case DRIZZLE_TYPE_LONGLONG:
531
 
  case DRIZZLE_TYPE_NULL:
532
 
  case DRIZZLE_TYPE_TIME:
533
 
  case DRIZZLE_TYPE_UUID:
534
 
  case DRIZZLE_TYPE_VARCHAR:
 
1762
    /* fall-through */
 
1763
  default:
 
1764
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
 
1765
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
 
1766
                           FIELDFLAG_DECIMAL) |
 
1767
                          (sql_field->flags & ZEROFILL_FLAG ?
 
1768
                           FIELDFLAG_ZEROFILL : 0) |
 
1769
                          f_settype((uint) sql_field->sql_type) |
 
1770
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
535
1771
    break;
536
1772
  }
537
 
 
538
 
  return 0;
 
1773
  if (!(sql_field->flags & NOT_NULL_FLAG))
 
1774
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
 
1775
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
 
1776
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
 
1777
  return(0);
539
1778
}
540
1779
 
541
 
static int prepare_create_table(Session *session,
542
 
                                HA_CREATE_INFO *create_info,
543
 
                                message::Table &create_proto,
544
 
                                AlterInfo *alter_info,
545
 
                                bool tmp_table,
546
 
                                uint32_t *db_options,
547
 
                                KeyInfo **key_info_buffer,
548
 
                                uint32_t *key_count,
549
 
                                int select_field_count)
 
1780
/*
 
1781
  Preparation for table creation
 
1782
 
 
1783
  SYNOPSIS
 
1784
    mysql_prepare_create_table()
 
1785
      thd                       Thread object.
 
1786
      create_info               Create information (like MAX_ROWS).
 
1787
      alter_info                List of columns and indexes to create
 
1788
      tmp_table                 If a temporary table is to be created.
 
1789
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
 
1790
      file                      The handler for the new table.
 
1791
      key_info_buffer     OUT   An array of KEY structs for the indexes.
 
1792
      key_count           OUT   The number of elements in the array.
 
1793
      select_field_count        The number of fields coming from a select table.
 
1794
 
 
1795
  DESCRIPTION
 
1796
    Prepares the table and key structures for table creation.
 
1797
 
 
1798
  NOTES
 
1799
    sets create_info->varchar if the table has a varchar
 
1800
 
 
1801
  RETURN VALUES
 
1802
    false    OK
 
1803
    true     error
 
1804
*/
 
1805
 
 
1806
static int
 
1807
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 
1808
                           Alter_info *alter_info,
 
1809
                           bool tmp_table,
 
1810
                               uint *db_options,
 
1811
                               handler *file, KEY **key_info_buffer,
 
1812
                               uint *key_count, int select_field_count)
550
1813
{
551
1814
  const char    *key_name;
552
 
  CreateField   *sql_field,*dup_field;
 
1815
  Create_field  *sql_field,*dup_field;
553
1816
  uint          field,null_fields,blob_columns,max_key_length;
554
1817
  ulong         record_offset= 0;
555
 
  KeyInfo               *key_info;
556
 
  KeyPartInfo *key_part_info;
 
1818
  KEY           *key_info;
 
1819
  KEY_PART_INFO *key_part_info;
557
1820
  int           timestamps= 0, timestamps_with_niladic= 0;
558
 
  int           dup_no;
 
1821
  int           field_no,dup_no;
559
1822
  int           select_field_pos,auto_increment=0;
560
 
  List<CreateField>::iterator it(alter_info->create_list.begin());
561
 
  List<CreateField>::iterator it2(alter_info->create_list.begin());
562
 
  uint32_t total_uneven_bit_length= 0;
563
 
 
564
 
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
 
1823
  List_iterator<Create_field> it(alter_info->create_list);
 
1824
  List_iterator<Create_field> it2(alter_info->create_list);
 
1825
  uint total_uneven_bit_length= 0;
565
1826
 
566
1827
  select_field_pos= alter_info->create_list.elements - select_field_count;
567
1828
  null_fields=blob_columns=0;
568
 
  max_key_length= engine->max_key_length();
 
1829
  create_info->varchar= 0;
 
1830
  max_key_length= file->max_key_length();
569
1831
 
570
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
1832
  for (field_no=0; (sql_field=it++) ; field_no++)
571
1833
  {
572
 
    const CHARSET_INFO *save_cs;
 
1834
    CHARSET_INFO *save_cs;
573
1835
 
574
1836
    /*
575
1837
      Initialize length from its original value (number of characters),
577
1839
      executing a prepared statement for the second time.
578
1840
    */
579
1841
    sql_field->length= sql_field->char_length;
580
 
 
581
1842
    if (!sql_field->charset)
582
1843
      sql_field->charset= create_info->default_table_charset;
583
 
 
584
1844
    /*
585
 
      table_charset is set in ALTER Table if we want change character set
 
1845
      table_charset is set in ALTER TABLE if we want change character set
586
1846
      for all varchar/char columns.
587
1847
      But the table charset must not affect the BLOB fields, so don't
588
1848
      allow to change my_charset_bin to somethig else.
592
1852
 
593
1853
    save_cs= sql_field->charset;
594
1854
    if ((sql_field->flags & BINCMP_FLAG) &&
595
 
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, MY_CS_BINSORT)))
 
1855
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
 
1856
                                                    MY_CS_BINSORT,MYF(0))))
596
1857
    {
597
1858
      char tmp[64];
598
 
      char *tmp_pos= tmp;
599
 
      strncpy(tmp_pos, save_cs->csname, sizeof(tmp)-4);
600
 
      tmp_pos+= strlen(tmp);
601
 
      strncpy(tmp_pos, STRING_WITH_LEN("_bin"));
 
1859
      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
 
1860
              STRING_WITH_LEN("_bin"));
602
1861
      my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
603
1862
      return(true);
604
1863
    }
607
1866
      Convert the default value from client character
608
1867
      set into the column character set if necessary.
609
1868
    */
610
 
    if (sql_field->def &&
 
1869
    if (sql_field->def && 
611
1870
        save_cs != sql_field->def->collation.collation &&
612
 
        (sql_field->sql_type == DRIZZLE_TYPE_ENUM))
 
1871
        (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
 
1872
         sql_field->sql_type == MYSQL_TYPE_STRING ||
 
1873
         sql_field->sql_type == MYSQL_TYPE_SET ||
 
1874
         sql_field->sql_type == MYSQL_TYPE_ENUM))
613
1875
    {
614
1876
      /*
615
 
        Starting from 5.1 we work here with a copy of CreateField
 
1877
        Starting from 5.1 we work here with a copy of Create_field
616
1878
        created by the caller, not with the instance that was
617
1879
        originally created during parsing. It's OK to create
618
1880
        a temporary item and initialize with it a member of the
631
1893
      }
632
1894
    }
633
1895
 
634
 
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
 
1896
    if (sql_field->sql_type == MYSQL_TYPE_SET ||
 
1897
        sql_field->sql_type == MYSQL_TYPE_ENUM)
635
1898
    {
636
 
      size_t dummy;
637
 
      const CHARSET_INFO * const cs= sql_field->charset;
 
1899
      uint32 dummy;
 
1900
      CHARSET_INFO *cs= sql_field->charset;
638
1901
      TYPELIB *interval= sql_field->interval;
639
1902
 
640
1903
      /*
649
1912
          occupied memory at the same time when we free this
650
1913
          sql_field -- at the end of execution.
651
1914
        */
652
 
        interval= sql_field->interval= typelib(session->mem_root,
 
1915
        interval= sql_field->interval= typelib(thd->mem_root,
653
1916
                                               sql_field->interval_list);
654
 
 
655
 
        List<String>::iterator int_it(sql_field->interval_list.begin());
 
1917
        List_iterator<String> int_it(sql_field->interval_list);
656
1918
        String conv, *tmp;
657
1919
        char comma_buf[4];
658
 
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
659
 
                                          (unsigned char*) comma_buf +
 
1920
        int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
 
1921
                                          (uchar*) comma_buf + 
660
1922
                                          sizeof(comma_buf));
661
1923
        assert(comma_length > 0);
662
 
 
663
 
        for (uint32_t i= 0; (tmp= int_it++); i++)
 
1924
        for (uint i= 0; (tmp= int_it++); i++)
664
1925
        {
665
 
          uint32_t lengthsp;
 
1926
          uint lengthsp;
666
1927
          if (String::needs_conversion(tmp->length(), tmp->charset(),
667
1928
                                       cs, &dummy))
668
1929
          {
669
 
            size_t cnv_errs;
 
1930
            uint cnv_errs;
670
1931
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
671
 
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
 
1932
            interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
 
1933
                                                  conv.length());
672
1934
            interval->type_lengths[i]= conv.length();
673
1935
          }
674
1936
 
676
1938
          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
677
1939
                                       interval->type_lengths[i]);
678
1940
          interval->type_lengths[i]= lengthsp;
679
 
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
680
 
        }
681
 
        sql_field->interval_list.clear(); // Don't need interval_list anymore
682
 
      }
683
 
 
684
 
      /* DRIZZLE_TYPE_ENUM */
685
 
      {
686
 
        uint32_t field_length;
687
 
        assert(sql_field->sql_type == DRIZZLE_TYPE_ENUM);
 
1941
          ((uchar *)interval->type_names[i])[lengthsp]= '\0';
 
1942
          if (sql_field->sql_type == MYSQL_TYPE_SET)
 
1943
          {
 
1944
            if (cs->coll->instr(cs, interval->type_names[i], 
 
1945
                                interval->type_lengths[i], 
 
1946
                                comma_buf, comma_length, NULL, 0))
 
1947
            {
 
1948
              my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
 
1949
              return(true);
 
1950
            }
 
1951
          }
 
1952
        }
 
1953
        sql_field->interval_list.empty(); // Don't need interval_list anymore
 
1954
      }
 
1955
 
 
1956
      if (sql_field->sql_type == MYSQL_TYPE_SET)
 
1957
      {
 
1958
        uint32 field_length;
 
1959
        if (sql_field->def != NULL)
 
1960
        {
 
1961
          char *not_used;
 
1962
          uint not_used2;
 
1963
          bool not_found= 0;
 
1964
          String str, *def= sql_field->def->val_str(&str);
 
1965
          if (def == NULL) /* SQL "NULL" maps to NULL */
 
1966
          {
 
1967
            if ((sql_field->flags & NOT_NULL_FLAG) != 0)
 
1968
            {
 
1969
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
 
1970
              return(true);
 
1971
            }
 
1972
 
 
1973
            /* else, NULL is an allowed value */
 
1974
            (void) find_set(interval, NULL, 0,
 
1975
                            cs, &not_used, &not_used2, &not_found);
 
1976
          }
 
1977
          else /* not NULL */
 
1978
          {
 
1979
            (void) find_set(interval, def->ptr(), def->length(),
 
1980
                            cs, &not_used, &not_used2, &not_found);
 
1981
          }
 
1982
 
 
1983
          if (not_found)
 
1984
          {
 
1985
            my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
 
1986
            return(true);
 
1987
          }
 
1988
        }
 
1989
        calculate_interval_lengths(cs, interval, &dummy, &field_length);
 
1990
        sql_field->length= field_length + (interval->count - 1);
 
1991
      }
 
1992
      else  /* MYSQL_TYPE_ENUM */
 
1993
      {
 
1994
        uint32 field_length;
 
1995
        assert(sql_field->sql_type == MYSQL_TYPE_ENUM);
688
1996
        if (sql_field->def != NULL)
689
1997
        {
690
1998
          String str, *def= sql_field->def->val_str(&str);
697
2005
            }
698
2006
 
699
2007
            /* else, the defaults yield the correct length for NULLs. */
700
 
          }
 
2008
          } 
701
2009
          else /* not NULL */
702
2010
          {
703
2011
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
704
 
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
 
2012
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
705
2013
            {
706
2014
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
707
2015
              return(true);
708
2016
            }
709
2017
          }
710
2018
        }
711
 
        uint32_t new_dummy;
712
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
2019
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
713
2020
        sql_field->length= field_length;
714
2021
      }
715
 
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
 
2022
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
716
2023
    }
717
2024
 
718
2025
    sql_field->create_length_to_internal_length();
719
 
    if (prepare_blob_field(session, sql_field))
 
2026
    if (prepare_blob_field(thd, sql_field))
720
2027
      return(true);
721
2028
 
722
2029
    if (!(sql_field->flags & NOT_NULL_FLAG))
758
2065
          sql_field->decimals=          dup_field->decimals;
759
2066
          sql_field->create_length_to_internal_length();
760
2067
          sql_field->unireg_check=      dup_field->unireg_check;
761
 
          /*
 
2068
          /* 
762
2069
            We're making one field from two, the result field will have
763
2070
            dup_field->flags as flags. If we've incremented null_fields
764
2071
            because of sql_field->flags, decrement it back.
773
2080
        }
774
2081
      }
775
2082
    }
776
 
 
777
 
    /** @todo Get rid of this MyISAM-specific crap. */
778
 
    if (not create_proto.engine().name().compare("MyISAM") &&
779
 
        ((sql_field->flags & BLOB_FLAG) ||
780
 
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
781
 
    {
 
2083
    /* Don't pack rows in old tables if the user has requested this */
 
2084
    if ((sql_field->flags & BLOB_FLAG) ||
 
2085
        (sql_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
782
2086
      (*db_options)|= HA_OPTION_PACK_RECORD;
783
 
    }
784
 
 
785
 
    it2= alter_info->create_list.begin();
 
2087
    it2.rewind();
786
2088
  }
787
2089
 
788
2090
  /* record_offset will be increased with 'length-of-null-bits' later */
789
2091
  record_offset= 0;
790
2092
  null_fields+= total_uneven_bit_length;
791
2093
 
792
 
  it= alter_info->create_list.begin();
 
2094
  it.rewind();
793
2095
  while ((sql_field=it++))
794
2096
  {
795
2097
    assert(sql_field->charset != 0);
796
2098
 
797
 
    if (prepare_create_field(sql_field, &blob_columns,
798
 
                             &timestamps, &timestamps_with_niladic))
 
2099
    if (prepare_create_field(sql_field, &blob_columns, 
 
2100
                             &timestamps, &timestamps_with_niladic,
 
2101
                             file->ha_table_flags()))
799
2102
      return(true);
 
2103
    if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
 
2104
      create_info->varchar= true;
800
2105
    sql_field->offset= record_offset;
801
2106
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
802
2107
      auto_increment++;
 
2108
    record_offset+= sql_field->pack_length;
803
2109
  }
804
2110
  if (timestamps_with_niladic > 1)
805
2111
  {
813
2119
    return(true);
814
2120
  }
815
2121
  if (auto_increment &&
816
 
      (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
 
2122
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
817
2123
  {
818
2124
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
819
2125
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
820
2126
    return(true);
821
2127
  }
822
2128
 
823
 
  if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
 
2129
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
824
2130
  {
825
2131
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
826
2132
               MYF(0));
829
2135
 
830
2136
  /* Create keys */
831
2137
 
832
 
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
833
 
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
834
 
  uint32_t key_parts=0, fk_key_count=0;
 
2138
  List_iterator<Key> key_iterator(alter_info->key_list);
 
2139
  List_iterator<Key> key_iterator2(alter_info->key_list);
 
2140
  uint key_parts=0, fk_key_count=0;
835
2141
  bool primary_key=0,unique_key=0;
836
2142
  Key *key, *key2;
837
 
  uint32_t tmp, key_number;
 
2143
  uint tmp, key_number;
838
2144
  /* special marker for keys to be ignored */
839
2145
  static char ignore_key[1];
840
2146
 
846
2152
    if (key->type == Key::FOREIGN_KEY)
847
2153
    {
848
2154
      fk_key_count++;
849
 
      if (((Foreign_key *)key)->validate(alter_info->create_list))
850
 
        return true;
851
 
 
852
2155
      Foreign_key *fk_key= (Foreign_key*) key;
853
 
 
854
 
      add_foreign_key_to_table_message(&create_proto,
855
 
                                       fk_key->name.str,
856
 
                                       fk_key->columns,
857
 
                                       fk_key->ref_table,
858
 
                                       fk_key->ref_columns,
859
 
                                       fk_key->delete_opt,
860
 
                                       fk_key->update_opt,
861
 
                                       fk_key->match_opt);
862
 
 
863
2156
      if (fk_key->ref_columns.elements &&
864
2157
          fk_key->ref_columns.elements != fk_key->columns.elements)
865
2158
      {
872
2165
      continue;
873
2166
    }
874
2167
    (*key_count)++;
875
 
    tmp= engine->max_key_parts();
 
2168
    tmp=file->max_key_parts();
876
2169
    if (key->columns.elements > tmp)
877
2170
    {
878
2171
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
880
2173
    }
881
2174
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
882
2175
      return(true);
883
 
    key_iterator2= alter_info->key_list.begin();
 
2176
    key_iterator2.rewind ();
884
2177
    if (key->type != Key::FOREIGN_KEY)
885
2178
    {
886
2179
      while ((key2 = key_iterator2++) != key)
894
2187
             key2->name.str != ignore_key &&
895
2188
             !foreign_key_prefix(key, key2)))
896
2189
        {
897
 
          /* @todo issue warning message */
 
2190
          /* TODO: issue warning message */
898
2191
          /* mark that the generated key should be ignored */
899
2192
          if (!key2->generated ||
900
2193
              (key->generated && key->columns.elements <
915
2208
    else
916
2209
      (*key_count)--;
917
2210
    if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
918
 
        is_primary_key_name(key->name.str))
 
2211
        !my_strcasecmp(system_charset_info,key->name.str, primary_key_name))
919
2212
    {
920
2213
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
921
2214
      return(true);
922
2215
    }
923
2216
  }
924
 
  tmp= engine->max_keys();
 
2217
  tmp=file->max_keys();
925
2218
  if (*key_count > tmp)
926
2219
  {
927
2220
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
928
2221
    return(true);
929
2222
  }
930
2223
 
931
 
  (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
932
 
  key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
 
2224
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
 
2225
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
933
2226
  if (!*key_info_buffer || ! key_part_info)
934
2227
    return(true);                               // Out of memory
935
2228
 
936
 
  key_iterator= alter_info->key_list.begin();
 
2229
  key_iterator.rewind();
937
2230
  key_number=0;
938
2231
  for (; (key=key_iterator++) ; key_number++)
939
2232
  {
940
 
    uint32_t key_length=0;
 
2233
    uint key_length=0;
941
2234
    Key_part_spec *column;
942
2235
 
943
2236
    if (key->name.str == ignore_key)
964
2257
    if (key->generated)
965
2258
      key_info->flags|= HA_GENERATED_KEY;
966
2259
 
967
 
    key_info->key_parts=(uint8_t) key->columns.elements;
 
2260
    key_info->key_parts=(uint8) key->columns.elements;
968
2261
    key_info->key_part=key_part_info;
969
2262
    key_info->usable_key_parts= key_number;
970
2263
    key_info->algorithm= key->key_create_info.algorithm;
971
2264
 
972
 
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
 
2265
    /* Take block size from key part or table part */
 
2266
    /*
 
2267
      TODO: Add warning if block size changes. We can't do it here, as
 
2268
      this may depend on the size of the key
 
2269
    */
 
2270
    key_info->block_size= (key->key_create_info.block_size ?
 
2271
                           key->key_create_info.block_size :
 
2272
                           create_info->key_block_size);
 
2273
 
 
2274
    if (key_info->block_size)
 
2275
      key_info->flags|= HA_USES_BLOCK_SIZE;
 
2276
 
 
2277
    uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
973
2278
                                           key->key_create_info.comment.str,
974
2279
                                           key->key_create_info.comment.str +
975
2280
                                           key->key_create_info.comment.length,
979
2284
    {
980
2285
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
981
2286
               key->key_create_info.comment.str,"INDEX COMMENT",
982
 
               (uint32_t) INDEX_COMMENT_MAXLEN);
983
 
      return -1;
 
2287
               (uint) INDEX_COMMENT_MAXLEN);
 
2288
      return(-1);
984
2289
    }
985
2290
 
986
2291
    key_info->comment.length= key->key_create_info.comment.length;
990
2295
      key_info->comment.str= key->key_create_info.comment.str;
991
2296
    }
992
2297
 
993
 
    message::Table::Field *protofield= NULL;
994
 
 
995
 
    List<Key_part_spec>::iterator cols(key->columns.begin());
996
 
    List<Key_part_spec>::iterator cols2(key->columns.begin());
997
 
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
 
2298
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
 
2299
    for (uint column_nr=0 ; (column=cols++) ; column_nr++)
998
2300
    {
999
 
      uint32_t length;
 
2301
      uint length;
1000
2302
      Key_part_spec *dup_column;
1001
 
      int proto_field_nr= 0;
1002
2303
 
1003
 
      it= alter_info->create_list.begin();
 
2304
      it.rewind();
1004
2305
      field=0;
1005
 
      while ((sql_field=it++) && ++proto_field_nr &&
 
2306
      while ((sql_field=it++) &&
1006
2307
             my_strcasecmp(system_charset_info,
1007
2308
                           column->field_name.str,
1008
2309
                           sql_field->field_name))
1009
 
      {
1010
2310
        field++;
1011
 
      }
1012
 
 
1013
2311
      if (!sql_field)
1014
2312
      {
1015
2313
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1016
2314
        return(true);
1017
2315
      }
1018
 
 
1019
2316
      while ((dup_column= cols2++) != column)
1020
2317
      {
1021
2318
        if (!my_strcasecmp(system_charset_info,
1022
 
                           column->field_name.str, dup_column->field_name.str))
 
2319
                           column->field_name.str, dup_column->field_name.str))
1023
2320
        {
1024
2321
          my_printf_error(ER_DUP_FIELDNAME,
1025
2322
                          ER(ER_DUP_FIELDNAME),MYF(0),
1027
2324
          return(true);
1028
2325
        }
1029
2326
      }
1030
 
      cols2= key->columns.begin();
1031
 
 
1032
 
      if (create_proto.field_size() > 0)
1033
 
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1034
 
 
 
2327
      cols2.rewind();
1035
2328
      {
1036
 
        column->length*= sql_field->charset->mbmaxlen;
1037
 
 
1038
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1039
 
        {
1040
 
          if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
1041
 
          {
1042
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1043
 
            return true;
1044
 
          }
1045
 
          if (! column->length)
1046
 
          {
1047
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
1048
 
            return true;
1049
 
          }
1050
 
        }
1051
 
 
1052
 
        if (! (sql_field->flags & NOT_NULL_FLAG))
1053
 
        {
1054
 
          if (key->type == Key::PRIMARY)
1055
 
          {
1056
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1057
 
            sql_field->flags|= NOT_NULL_FLAG;
 
2329
        column->length*= sql_field->charset->mbmaxlen;
 
2330
 
 
2331
        if (f_is_blob(sql_field->pack_flag))
 
2332
        {
 
2333
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
2334
          {
 
2335
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
2336
            return(true);
 
2337
          }
 
2338
          if (!column->length)
 
2339
          {
 
2340
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
2341
            return(true);
 
2342
          }
 
2343
        }
 
2344
        if (!(sql_field->flags & NOT_NULL_FLAG))
 
2345
        {
 
2346
          if (key->type == Key::PRIMARY)
 
2347
          {
 
2348
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
2349
            sql_field->flags|= NOT_NULL_FLAG;
 
2350
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
1058
2351
            null_fields--;
1059
 
 
1060
 
            if (protofield)
1061
 
            {
1062
 
              message::Table::Field::FieldConstraints *constraints;
1063
 
              constraints= protofield->mutable_constraints();
1064
 
              constraints->set_is_notnull(true);
1065
 
            }
1066
 
 
1067
 
          }
1068
 
          else
 
2352
          }
 
2353
          else
1069
2354
          {
1070
2355
            key_info->flags|= HA_NULL_PART_KEY;
1071
 
            if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
 
2356
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
1072
2357
            {
1073
2358
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1074
 
              return true;
 
2359
              return(true);
1075
2360
            }
1076
2361
          }
1077
 
        }
1078
 
 
1079
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1080
 
        {
1081
 
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1082
 
            auto_increment--;                   // Field is used
1083
 
        }
 
2362
        }
 
2363
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
2364
        {
 
2365
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
 
2366
            auto_increment--;                   // Field is used
 
2367
        }
1084
2368
      }
1085
2369
 
1086
2370
      key_part_info->fieldnr= field;
1087
 
      key_part_info->offset=  (uint16_t) sql_field->offset;
1088
 
      key_part_info->key_type= 0;
 
2371
      key_part_info->offset=  (uint16) sql_field->offset;
 
2372
      key_part_info->key_type=sql_field->pack_flag;
1089
2373
      length= sql_field->key_length;
1090
2374
 
1091
2375
      if (column->length)
1092
2376
      {
1093
 
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
2377
        if (f_is_blob(sql_field->pack_flag))
1094
2378
        {
1095
2379
          if ((length=column->length) > max_key_length ||
1096
 
              length > engine->max_key_part_length())
 
2380
              length > file->max_key_part_length())
1097
2381
          {
1098
 
            length= min(max_key_length, engine->max_key_part_length());
 
2382
            length=min(max_key_length, file->max_key_part_length());
1099
2383
            if (key->type == Key::MULTIPLE)
1100
2384
            {
1101
2385
              /* not a critical problem */
1102
 
              char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2386
              char warn_buff[MYSQL_ERRMSG_SIZE];
1103
2387
              snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1104
2388
                       length);
1105
 
              push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2389
              push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1106
2390
                           ER_TOO_LONG_KEY, warn_buff);
1107
2391
              /* Align key length to multibyte char boundary */
1108
2392
              length-= length % sql_field->charset->mbmaxlen;
1115
2399
          }
1116
2400
        }
1117
2401
        else if ((column->length > length ||
1118
 
            ! Field::type_can_have_key_part(sql_field->sql_type)))
 
2402
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
 
2403
                   ((f_is_packed(sql_field->pack_flag) ||
 
2404
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
 
2405
                      (key_info->flags & HA_NOSAME))) &&
 
2406
                    column->length != length)))
1119
2407
        {
1120
2408
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1121
2409
          return(true);
1122
2410
        }
1123
 
        else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
1124
 
        {
 
2411
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1125
2412
          length=column->length;
1126
 
        }
1127
2413
      }
1128
2414
      else if (length == 0)
1129
2415
      {
1130
2416
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1131
2417
          return(true);
1132
2418
      }
1133
 
      if (length > engine->max_key_part_length())
 
2419
      if (length > file->max_key_part_length())
1134
2420
      {
1135
 
        length= engine->max_key_part_length();
 
2421
        length= file->max_key_part_length();
1136
2422
        if (key->type == Key::MULTIPLE)
1137
2423
        {
1138
2424
          /* not a critical problem */
1139
 
          char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
2425
          char warn_buff[MYSQL_ERRMSG_SIZE];
1140
2426
          snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1141
2427
                   length);
1142
 
          push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2428
          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1143
2429
                       ER_TOO_LONG_KEY, warn_buff);
1144
2430
          /* Align key length to multibyte char boundary */
1145
2431
          length-= length % sql_field->charset->mbmaxlen;
1150
2436
          return(true);
1151
2437
        }
1152
2438
      }
1153
 
      key_part_info->length=(uint16_t) length;
 
2439
      key_part_info->length=(uint16) length;
1154
2440
      /* Use packed keys for long strings on the first column */
1155
2441
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1156
 
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1157
 
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1158
 
            sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
 
2442
          (length >= KEY_DEFAULT_PACK_LENGTH &&
 
2443
           (sql_field->sql_type == MYSQL_TYPE_STRING ||
 
2444
            sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
 
2445
            sql_field->pack_flag & FIELDFLAG_BLOB)))
1159
2446
      {
1160
 
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1161
 
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1162
 
        {
1163
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1164
 
        }
1165
 
        else
1166
 
        {
1167
 
          key_info->flags|= HA_PACK_KEY;
1168
 
        }
 
2447
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
 
2448
            sql_field->sql_type == MYSQL_TYPE_VARCHAR)
 
2449
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
2450
        else
 
2451
          key_info->flags|= HA_PACK_KEY;
1169
2452
      }
1170
2453
      /* Check if the key segment is partial, set the key flag accordingly */
1171
2454
      if (length != sql_field->key_length)
1185
2468
                       MYF(0));
1186
2469
            return(true);
1187
2470
          }
1188
 
          static const char pkey_name[]= "PRIMARY";
1189
 
          key_name=pkey_name;
 
2471
          key_name=primary_key_name;
1190
2472
          primary_key=1;
1191
2473
        }
1192
2474
        else if (!(key_name= key->name.str))
1200
2482
        key_info->name=(char*) key_name;
1201
2483
      }
1202
2484
    }
1203
 
 
1204
2485
    if (!key_info->name || check_column_name(key_info->name))
1205
2486
    {
1206
2487
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1207
2488
      return(true);
1208
2489
    }
1209
 
 
1210
2490
    if (!(key_info->flags & HA_NULL_PART_KEY))
1211
 
    {
1212
2491
      unique_key=1;
1213
 
    }
1214
 
 
1215
 
    key_info->key_length=(uint16_t) key_length;
1216
 
 
 
2492
    key_info->key_length=(uint16) key_length;
1217
2493
    if (key_length > max_key_length)
1218
2494
    {
1219
2495
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1220
2496
      return(true);
1221
2497
    }
1222
 
 
1223
2498
    key_info++;
1224
2499
  }
1225
 
 
1226
2500
  if (!unique_key && !primary_key &&
1227
 
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
 
2501
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1228
2502
  {
1229
2503
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1230
2504
    return(true);
1231
2505
  }
1232
 
 
1233
2506
  if (auto_increment > 0)
1234
2507
  {
1235
2508
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1236
2509
    return(true);
1237
2510
  }
1238
2511
  /* Sort keys in optimized order */
1239
 
  internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1240
 
                     (qsort_cmp) sort_keys);
 
2512
  my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
 
2513
           (qsort_cmp) sort_keys);
 
2514
  create_info->null_bits= null_fields;
1241
2515
 
1242
2516
  /* Check fields. */
1243
 
  it= alter_info->create_list.begin();
 
2517
  it.rewind();
1244
2518
  while ((sql_field=it++))
1245
2519
  {
1246
2520
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1247
2521
 
1248
 
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
 
2522
    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
1249
2523
        !sql_field->def &&
1250
 
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
 
2524
        sql_field->sql_type == MYSQL_TYPE_TIMESTAMP &&
1251
2525
        (sql_field->flags & NOT_NULL_FLAG) &&
1252
2526
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1253
2527
    {
1273
2547
  return(false);
1274
2548
}
1275
2549
 
 
2550
 
 
2551
/*
 
2552
  Set table default charset, if not set
 
2553
 
 
2554
  SYNOPSIS
 
2555
    set_table_default_charset()
 
2556
    create_info        Table create information
 
2557
 
 
2558
  DESCRIPTION
 
2559
    If the table character set was not given explicitely,
 
2560
    let's fetch the database default character set and
 
2561
    apply it to the table.
 
2562
*/
 
2563
 
 
2564
static void set_table_default_charset(THD *thd,
 
2565
                                      HA_CREATE_INFO *create_info, char *db)
 
2566
{
 
2567
  /*
 
2568
    If the table character set was not given explicitly,
 
2569
    let's fetch the database default character set and
 
2570
    apply it to the table.
 
2571
  */
 
2572
  if (!create_info->default_table_charset)
 
2573
  {
 
2574
    HA_CREATE_INFO db_info;
 
2575
 
 
2576
    load_db_opt_by_name(thd, db, &db_info);
 
2577
 
 
2578
    create_info->default_table_charset= db_info.default_table_charset;
 
2579
  }
 
2580
}
 
2581
 
 
2582
 
1276
2583
/*
1277
2584
  Extend long VARCHAR fields to blob & prepare field if it's a blob
1278
2585
 
1286
2593
        In this case the error is given
1287
2594
*/
1288
2595
 
1289
 
static bool prepare_blob_field(Session *,
1290
 
                               CreateField *sql_field)
 
2596
static bool prepare_blob_field(THD *thd __attribute__((__unused__)),
 
2597
                               Create_field *sql_field)
1291
2598
{
1292
2599
 
1293
2600
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
1295
2602
  {
1296
2603
    my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1297
2604
             MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1298
 
    return 1;
 
2605
    return(1);
1299
2606
  }
1300
 
 
 
2607
    
1301
2608
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1302
2609
  {
1303
 
    if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
2610
    if (sql_field->sql_type == MYSQL_TYPE_BLOB)
1304
2611
    {
1305
2612
      /* The user has given a length to the blob column */
 
2613
      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1306
2614
      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1307
2615
    }
1308
2616
    sql_field->length= 0;
1309
2617
  }
1310
 
  return 0;
 
2618
  return(0);
1311
2619
}
1312
2620
 
1313
 
static bool locked_create_event(Session *session,
1314
 
                                const identifier::Table &identifier,
1315
 
                                HA_CREATE_INFO *create_info,
1316
 
                                message::Table &table_proto,
1317
 
                                AlterInfo *alter_info,
1318
 
                                bool is_if_not_exists,
1319
 
                                bool internal_tmp_table,
1320
 
                                uint db_options,
1321
 
                                uint key_count,
1322
 
                                KeyInfo *key_info_buffer)
 
2621
 
 
2622
/*
 
2623
  Preparation of Create_field for SP function return values.
 
2624
  Based on code used in the inner loop of mysql_prepare_create_table()
 
2625
  above.
 
2626
 
 
2627
  SYNOPSIS
 
2628
    sp_prepare_create_field()
 
2629
    thd                 Thread object
 
2630
    sql_field           Field to prepare
 
2631
 
 
2632
  DESCRIPTION
 
2633
    Prepares the field structures for field creation.
 
2634
 
 
2635
*/
 
2636
 
 
2637
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
1323
2638
{
1324
 
  bool error= true;
1325
 
 
1326
 
  {
1327
 
 
1328
 
    /*
1329
 
      @note if we are building a temp table we need to check to see if a temp table
1330
 
      already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1331
 
      to create a table under a temporary table.
1332
 
    */
1333
 
    bool exists= 
1334
 
      plugin::StorageEngine::doesTableExist(*session, identifier, 
1335
 
                                            identifier.getType() != message::Table::STANDARD );
1336
 
 
1337
 
    if (exists)
1338
 
    {
1339
 
      if (is_if_not_exists)
1340
 
      {
1341
 
        error= false;
1342
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1343
 
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1344
 
                            identifier.getTableName().c_str());
1345
 
        create_info->table_existed= 1;          // Mark that table existed
1346
 
        return error;
1347
 
      }
1348
 
 
1349
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1350
 
 
1351
 
      return error;
1352
 
    }
1353
 
 
1354
 
    if (identifier.getType() == message::Table::STANDARD) // We have a real table
1355
 
    {
1356
 
      /*
1357
 
        We don't assert here, but check the result, because the table could be
1358
 
        in the table definition cache and in the same time the .frm could be
1359
 
        missing from the disk, in case of manual intervention which deletes
1360
 
        the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1361
 
        Then she could create the table. This case is pretty obscure and
1362
 
        therefore we don't introduce a new error message only for it.
1363
 
      */
1364
 
      /*
1365
 
        @todo improve this error condition.
1366
 
      */
1367
 
      if (definition::Cache::singleton().find(identifier.getKey()))
1368
 
      {
1369
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1370
 
 
1371
 
        return error;
1372
 
      }
1373
 
    }
1374
 
  }
1375
 
 
1376
 
  session->set_proc_info("creating table");
1377
 
  create_info->table_existed= 0;                // Mark that table is created
1378
 
 
1379
 
  create_info->table_options= db_options;
1380
 
 
1381
 
  if (not rea_create_table(session, identifier,
1382
 
                           table_proto,
1383
 
                           create_info, alter_info->create_list,
1384
 
                           key_count, key_info_buffer))
1385
 
  {
1386
 
    return error;
1387
 
  }
1388
 
 
1389
 
  if (identifier.getType() == message::Table::TEMPORARY)
1390
 
  {
1391
 
    /* Open table and put in temporary table list */
1392
 
    if (not (session->open_temporary_table(identifier)))
1393
 
    {
1394
 
      (void) session->rm_temporary_table(identifier);
1395
 
      return error;
1396
 
    }
1397
 
  }
1398
 
 
1399
 
  /* 
1400
 
    We keep this behind the lock to make sure ordering is correct for a table.
1401
 
    This is a very unlikely problem where before we would write out to the
1402
 
    trans log, someone would do a delete/create operation.
1403
 
  */
1404
 
 
1405
 
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1406
 
  {
1407
 
    TransactionServices &transaction_services= TransactionServices::singleton();
1408
 
    transaction_services.createTable(*session, table_proto);
1409
 
  }
1410
 
 
1411
 
  return false;
 
2639
  if (sql_field->sql_type == MYSQL_TYPE_SET ||
 
2640
      sql_field->sql_type == MYSQL_TYPE_ENUM)
 
2641
  {
 
2642
    uint32 field_length, dummy;
 
2643
    if (sql_field->sql_type == MYSQL_TYPE_SET)
 
2644
    {
 
2645
      calculate_interval_lengths(sql_field->charset,
 
2646
                                 sql_field->interval, &dummy, 
 
2647
                                 &field_length);
 
2648
      sql_field->length= field_length + 
 
2649
                         (sql_field->interval->count - 1);
 
2650
    }
 
2651
    else /* MYSQL_TYPE_ENUM */
 
2652
    {
 
2653
      calculate_interval_lengths(sql_field->charset,
 
2654
                                 sql_field->interval,
 
2655
                                 &field_length, &dummy);
 
2656
      sql_field->length= field_length;
 
2657
    }
 
2658
    set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
 
2659
  }
 
2660
 
 
2661
  sql_field->create_length_to_internal_length();
 
2662
  assert(sql_field->def == 0);
 
2663
  /* Can't go wrong as sql_field->def is not defined */
 
2664
  (void) prepare_blob_field(thd, sql_field);
1412
2665
}
1413
2666
 
1414
2667
 
1415
2668
/*
1416
 
  Ignore the name of this function... it locks :(
1417
 
 
1418
2669
  Create a table
1419
2670
 
1420
2671
  SYNOPSIS
1421
 
    create_table_no_lock()
1422
 
    session                     Thread object
 
2672
    mysql_create_table_no_lock()
 
2673
    thd                 Thread object
1423
2674
    db                  Database
1424
2675
    table_name          Table name
1425
2676
    create_info         Create information (like MAX_ROWS)
1426
2677
    fields              List of fields to create
1427
2678
    keys                List of keys to create
1428
2679
    internal_tmp_table  Set to 1 if this is an internal temporary table
1429
 
                        (From ALTER Table)
1430
 
    select_field_count
 
2680
                        (From ALTER TABLE)
 
2681
    select_field_count  
1431
2682
 
1432
2683
  DESCRIPTION
1433
2684
    If one creates a temporary table, this is automatically opened
1434
2685
 
1435
2686
    Note that this function assumes that caller already have taken
1436
2687
    name-lock on table being created or used some other way to ensure
1437
 
    that concurrent operations won't intervene. create_table()
 
2688
    that concurrent operations won't intervene. mysql_create_table()
1438
2689
    is a wrapper that can be used for this.
1439
2690
 
 
2691
    no_log is needed for the case of CREATE ... SELECT,
 
2692
    as the logging will be done later in sql_insert.cc
 
2693
    select_field_count is also used for CREATE ... SELECT,
 
2694
    and must be zero for standard create of table.
 
2695
 
1440
2696
  RETURN VALUES
1441
2697
    false OK
1442
2698
    true  error
1443
2699
*/
1444
2700
 
1445
 
bool create_table_no_lock(Session *session,
1446
 
                                const identifier::Table &identifier,
 
2701
bool mysql_create_table_no_lock(THD *thd,
 
2702
                                const char *db, const char *table_name,
1447
2703
                                HA_CREATE_INFO *create_info,
1448
 
                                message::Table &table_proto,
1449
 
                                AlterInfo *alter_info,
 
2704
                                Alter_info *alter_info,
1450
2705
                                bool internal_tmp_table,
1451
 
                                uint32_t select_field_count,
1452
 
                                bool is_if_not_exists)
 
2706
                                uint select_field_count)
1453
2707
{
 
2708
  char          path[FN_REFLEN];
 
2709
  uint          path_length;
 
2710
  const char    *alias;
1454
2711
  uint          db_options, key_count;
1455
 
  KeyInfo               *key_info_buffer;
 
2712
  KEY           *key_info_buffer;
 
2713
  handler       *file;
1456
2714
  bool          error= true;
1457
 
 
1458
2715
  /* Check for duplicate fields and check type of table to create */
1459
 
  if (not alter_info->create_list.elements)
 
2716
  if (!alter_info->create_list.elements)
1460
2717
  {
1461
2718
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1462
2719
               MYF(0));
1463
 
    return true;
 
2720
    return(true);
1464
2721
  }
1465
 
  assert(identifier.getTableName() == table_proto.name());
 
2722
  if (check_engine(thd, table_name, create_info))
 
2723
    return(true);
1466
2724
  db_options= create_info->table_options;
1467
 
 
1468
 
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1469
 
 
1470
 
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1471
 
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1472
 
                               internal_tmp_table,
1473
 
                               &db_options,
1474
 
                               &key_info_buffer, &key_count,
1475
 
                               select_field_count))
1476
 
  {
1477
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1478
 
    error= locked_create_event(session,
1479
 
                               identifier,
1480
 
                               create_info,
1481
 
                               table_proto,
1482
 
                               alter_info,
1483
 
                               is_if_not_exists,
1484
 
                               internal_tmp_table,
1485
 
                               db_options, key_count,
1486
 
                               key_info_buffer);
1487
 
  }
1488
 
 
1489
 
  session->set_proc_info("After create");
1490
 
 
 
2725
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
 
2726
    db_options|=HA_OPTION_PACK_RECORD;
 
2727
  alias= table_case_name(create_info, table_name);
 
2728
  if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
 
2729
                              create_info->db_type)))
 
2730
  {
 
2731
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
 
2732
    return(true);
 
2733
  }
 
2734
 
 
2735
  set_table_default_charset(thd, create_info, (char*) db);
 
2736
 
 
2737
  if (mysql_prepare_create_table(thd, create_info, alter_info,
 
2738
                                 internal_tmp_table,
 
2739
                                 &db_options, file,
 
2740
                          &key_info_buffer, &key_count,
 
2741
                          select_field_count))
 
2742
    goto err;
 
2743
 
 
2744
      /* Check if table exists */
 
2745
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2746
  {
 
2747
    path_length= build_tmptable_filename(thd, path, sizeof(path));
 
2748
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
2749
  }
 
2750
  else  
 
2751
  {
 
2752
 #ifdef FN_DEVCHAR
 
2753
    /* check if the table name contains FN_DEVCHAR when defined */
 
2754
    if (strchr(alias, FN_DEVCHAR))
 
2755
    {
 
2756
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
 
2757
      return(true);
 
2758
    }
 
2759
#endif
 
2760
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
 
2761
                                      internal_tmp_table ? FN_IS_TMP : 0);
 
2762
  }
 
2763
 
 
2764
  /* Check if table already exists */
 
2765
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
2766
      find_temporary_table(thd, db, table_name))
 
2767
  {
 
2768
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2769
    {
 
2770
      create_info->table_existed= 1;            // Mark that table existed
 
2771
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
2772
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
2773
                          alias);
 
2774
      error= 0;
 
2775
      goto err;
 
2776
    }
 
2777
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
 
2778
    goto err;
 
2779
  }
 
2780
 
 
2781
  VOID(pthread_mutex_lock(&LOCK_open));
 
2782
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2783
  {
 
2784
    if (!access(path,F_OK))
 
2785
    {
 
2786
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2787
        goto warn;
 
2788
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
2789
      goto unlock_and_end;
 
2790
    }
 
2791
    /*
 
2792
      We don't assert here, but check the result, because the table could be
 
2793
      in the table definition cache and in the same time the .frm could be
 
2794
      missing from the disk, in case of manual intervention which deletes
 
2795
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
2796
      Then she could create the table. This case is pretty obscure and
 
2797
      therefore we don't introduce a new error message only for it.
 
2798
    */
 
2799
    if (get_cached_table_share(db, alias))
 
2800
    {
 
2801
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2802
      goto unlock_and_end;
 
2803
    }
 
2804
  }
 
2805
 
 
2806
  /*
 
2807
    Check that table with given name does not already
 
2808
    exist in any storage engine. In such a case it should
 
2809
    be discovered and the error ER_TABLE_EXISTS_ERROR be returned
 
2810
    unless user specified CREATE TABLE IF EXISTS
 
2811
    The LOCK_open mutex has been locked to make sure no
 
2812
    one else is attempting to discover the table. Since
 
2813
    it's not on disk as a frm file, no one could be using it!
 
2814
  */
 
2815
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2816
  {
 
2817
    bool create_if_not_exists =
 
2818
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
 
2819
    int retcode = ha_table_exists_in_engine(thd, db, table_name);
 
2820
    switch (retcode)
 
2821
    {
 
2822
      case HA_ERR_NO_SUCH_TABLE:
 
2823
        /* Normal case, no table exists. we can go and create it */
 
2824
        break;
 
2825
      case HA_ERR_TABLE_EXIST:
 
2826
 
 
2827
      if (create_if_not_exists)
 
2828
        goto warn;
 
2829
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
2830
      goto unlock_and_end;
 
2831
        break;
 
2832
      default:
 
2833
        my_error(retcode, MYF(0),table_name);
 
2834
        goto unlock_and_end;
 
2835
    }
 
2836
  }
 
2837
 
 
2838
  thd_proc_info(thd, "creating table");
 
2839
  create_info->table_existed= 0;                // Mark that table is created
 
2840
 
 
2841
#ifdef HAVE_READLINK
 
2842
  if (test_if_data_home_dir(create_info->data_file_name))
 
2843
  {
 
2844
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
 
2845
    goto unlock_and_end;
 
2846
  }
 
2847
  if (test_if_data_home_dir(create_info->index_file_name))
 
2848
  {
 
2849
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
 
2850
    goto unlock_and_end;
 
2851
  }
 
2852
 
 
2853
  if (!my_use_symdir)
 
2854
#endif /* HAVE_READLINK */
 
2855
  {
 
2856
    if (create_info->data_file_name)
 
2857
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
 
2858
                   "DATA DIRECTORY option ignored");
 
2859
    if (create_info->index_file_name)
 
2860
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
 
2861
                   "INDEX DIRECTORY option ignored");
 
2862
    create_info->data_file_name= create_info->index_file_name= 0;
 
2863
  }
 
2864
  create_info->table_options=db_options;
 
2865
 
 
2866
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
 
2867
  if (rea_create_table(thd, path, db, table_name,
 
2868
                       create_info, alter_info->create_list,
 
2869
                       key_count, key_info_buffer, file))
 
2870
    goto unlock_and_end;
 
2871
 
 
2872
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2873
  {
 
2874
    /* Open table and put in temporary table list */
 
2875
    if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
 
2876
    {
 
2877
      (void) rm_temporary_table(create_info->db_type, path, false);
 
2878
      goto unlock_and_end;
 
2879
    }
 
2880
    thd->thread_specific_used= true;
 
2881
  }
 
2882
 
 
2883
  /*
 
2884
    Don't write statement if:
 
2885
    - It is an internal temporary table,
 
2886
    - Row-based logging is used and it we are creating a temporary table, or
 
2887
    - The binary log is not open.
 
2888
    Otherwise, the statement shall be binlogged.
 
2889
   */
 
2890
  if (!internal_tmp_table &&
 
2891
      (!thd->current_stmt_binlog_row_based ||
 
2892
       (thd->current_stmt_binlog_row_based &&
 
2893
        !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
2894
    write_bin_log(thd, true, thd->query, thd->query_length);
 
2895
  error= false;
 
2896
unlock_and_end:
 
2897
  VOID(pthread_mutex_unlock(&LOCK_open));
 
2898
 
 
2899
err:
 
2900
  thd_proc_info(thd, "After create");
 
2901
  delete file;
1491
2902
  return(error);
 
2903
 
 
2904
warn:
 
2905
  error= false;
 
2906
  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
2907
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
2908
                      alias);
 
2909
  create_info->table_existed= 1;                // Mark that table existed
 
2910
  goto unlock_and_end;
1492
2911
}
1493
2912
 
1494
 
/**
1495
 
  @note the following two methods implement create [temporary] table.
 
2913
 
 
2914
/*
 
2915
  Database locking aware wrapper for mysql_create_table_no_lock(),
1496
2916
*/
1497
 
static bool drizzle_create_table(Session *session,
1498
 
                                 const identifier::Table &identifier,
1499
 
                                 HA_CREATE_INFO *create_info,
1500
 
                                 message::Table &table_proto,
1501
 
                                 AlterInfo *alter_info,
1502
 
                                 bool internal_tmp_table,
1503
 
                                 uint32_t select_field_count,
1504
 
                                 bool is_if_not_exists)
 
2917
 
 
2918
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
 
2919
                        HA_CREATE_INFO *create_info,
 
2920
                        Alter_info *alter_info,
 
2921
                        bool internal_tmp_table,
 
2922
                        uint select_field_count)
1505
2923
{
1506
 
  Table *name_lock= NULL;
 
2924
  TABLE *name_lock= 0;
1507
2925
  bool result;
1508
2926
 
1509
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1510
 
  {
1511
 
    result= true;
1512
 
  }
1513
 
  else if (name_lock == NULL)
1514
 
  {
1515
 
    if (is_if_not_exists)
1516
 
    {
1517
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1518
 
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1519
 
                          identifier.getTableName().c_str());
1520
 
      create_info->table_existed= 1;
1521
 
      result= false;
1522
 
    }
1523
 
    else
1524
 
    {
1525
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
2927
  /* Wait for any database locks */
 
2928
  pthread_mutex_lock(&LOCK_lock_db);
 
2929
  while (!thd->killed &&
 
2930
         hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
 
2931
  {
 
2932
    wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
 
2933
    pthread_mutex_lock(&LOCK_lock_db);
 
2934
  }
 
2935
 
 
2936
  if (thd->killed)
 
2937
  {
 
2938
    pthread_mutex_unlock(&LOCK_lock_db);
 
2939
    return(true);
 
2940
  }
 
2941
  creating_table++;
 
2942
  pthread_mutex_unlock(&LOCK_lock_db);
 
2943
 
 
2944
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2945
  {
 
2946
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
2947
    {
1526
2948
      result= true;
1527
 
    }
1528
 
  }
1529
 
  else
1530
 
  {
1531
 
    result= create_table_no_lock(session,
1532
 
                                       identifier,
1533
 
                                       create_info,
1534
 
                                       table_proto,
1535
 
                                       alter_info,
1536
 
                                       internal_tmp_table,
1537
 
                                       select_field_count,
1538
 
                                       is_if_not_exists);
1539
 
  }
1540
 
 
 
2949
      goto unlock;
 
2950
    }
 
2951
    if (!name_lock)
 
2952
    {
 
2953
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2954
      {
 
2955
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
2956
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
2957
                            table_name);
 
2958
        create_info->table_existed= 1;
 
2959
        result= false;
 
2960
      }
 
2961
      else
 
2962
      {
 
2963
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
2964
        result= true;
 
2965
      }
 
2966
      goto unlock;
 
2967
    }
 
2968
  }
 
2969
 
 
2970
  result= mysql_create_table_no_lock(thd, db, table_name, create_info,
 
2971
                                     alter_info,
 
2972
                                     internal_tmp_table,
 
2973
                                     select_field_count);
 
2974
 
 
2975
unlock:
1541
2976
  if (name_lock)
1542
2977
  {
1543
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1544
 
    session->unlink_open_table(name_lock);
 
2978
    pthread_mutex_lock(&LOCK_open);
 
2979
    unlink_open_table(thd, name_lock, false);
 
2980
    pthread_mutex_unlock(&LOCK_open);
1545
2981
  }
1546
 
 
 
2982
  pthread_mutex_lock(&LOCK_lock_db);
 
2983
  if (!--creating_table && creating_database)
 
2984
    pthread_cond_signal(&COND_refresh);
 
2985
  pthread_mutex_unlock(&LOCK_lock_db);
1547
2986
  return(result);
1548
2987
}
1549
2988
 
1550
2989
 
1551
2990
/*
1552
 
  Database locking aware wrapper for create_table_no_lock(),
1553
 
*/
1554
 
bool create_table(Session *session,
1555
 
                        const identifier::Table &identifier,
1556
 
                        HA_CREATE_INFO *create_info,
1557
 
                        message::Table &table_proto,
1558
 
                        AlterInfo *alter_info,
1559
 
                        bool internal_tmp_table,
1560
 
                        uint32_t select_field_count,
1561
 
                        bool is_if_not_exists)
1562
 
{
1563
 
  if (identifier.isTmp())
1564
 
  {
1565
 
    return create_table_no_lock(session,
1566
 
                                      identifier,
1567
 
                                      create_info,
1568
 
                                      table_proto,
1569
 
                                      alter_info,
1570
 
                                      internal_tmp_table,
1571
 
                                      select_field_count,
1572
 
                                      is_if_not_exists);
1573
 
  }
1574
 
 
1575
 
  return drizzle_create_table(session,
1576
 
                              identifier,
1577
 
                              create_info,
1578
 
                              table_proto,
1579
 
                              alter_info,
1580
 
                              internal_tmp_table,
1581
 
                              select_field_count,
1582
 
                              is_if_not_exists);
1583
 
}
1584
 
 
1585
 
 
1586
 
/*
1587
2991
** Give the key name after the first field with an optional '_#' after
1588
2992
**/
1589
2993
 
1590
2994
static bool
1591
 
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
 
2995
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1592
2996
{
1593
 
  for (KeyInfo *key=start ; key != end ; key++)
 
2997
  for (KEY *key=start ; key != end ; key++)
1594
2998
    if (!my_strcasecmp(system_charset_info,name,key->name))
1595
2999
      return 1;
1596
3000
  return 0;
1598
3002
 
1599
3003
 
1600
3004
static char *
1601
 
make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
 
3005
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
1602
3006
{
1603
3007
  char buff[MAX_FIELD_NAME],*buff_end;
1604
3008
 
1605
3009
  if (!check_if_keyname_exists(field_name,start,end) &&
1606
 
      !is_primary_key_name(field_name))
 
3010
      my_strcasecmp(system_charset_info,field_name,primary_key_name))
1607
3011
    return (char*) field_name;                  // Use fieldname
1608
 
 
1609
 
  buff_end= strncpy(buff, field_name, sizeof(buff)-4);
1610
 
  buff_end+= strlen(buff);
 
3012
  buff_end=strmake(buff,field_name, sizeof(buff)-4);
1611
3013
 
1612
3014
  /*
1613
3015
    Only 3 chars + '\0' left, so need to limit to 2 digit
1614
3016
    This is ok as we can't have more than 100 keys anyway
1615
3017
  */
1616
 
  for (uint32_t i=2 ; i< 100; i++)
 
3018
  for (uint i=2 ; i< 100; i++)
1617
3019
  {
1618
3020
    *buff_end= '_';
1619
 
    internal::int10_to_str(i, buff_end+1, 10);
 
3021
    int10_to_str(i, buff_end+1, 10);
1620
3022
    if (!check_if_keyname_exists(buff,start,end))
1621
 
      return memory::sql_strdup(buff);
 
3023
      return sql_strdup(buff);
1622
3024
  }
1623
3025
  return (char*) "not_specified";               // Should never happen
1624
3026
}
1628
3030
** Alter a table definition
1629
3031
****************************************************************************/
1630
3032
 
 
3033
 
1631
3034
/*
1632
3035
  Rename a table.
1633
3036
 
1634
3037
  SYNOPSIS
1635
 
    rename_table()
1636
 
      session
1637
 
      base                      The plugin::StorageEngine handle.
 
3038
    mysql_rename_table()
 
3039
      base                      The handlerton handle.
1638
3040
      old_db                    The old database name.
1639
3041
      old_name                  The old table name.
1640
3042
      new_db                    The new database name.
1641
3043
      new_name                  The new table name.
 
3044
      flags                     flags for build_table_filename().
 
3045
                                FN_FROM_IS_TMP old_name is temporary.
 
3046
                                FN_TO_IS_TMP   new_name is temporary.
 
3047
                                NO_FRM_RENAME  Don't rename the FRM file
 
3048
                                but only the table in the storage engine.
1642
3049
 
1643
3050
  RETURN
1644
3051
    false   OK
1646
3053
*/
1647
3054
 
1648
3055
bool
1649
 
rename_table(Session &session,
1650
 
                   plugin::StorageEngine *base,
1651
 
                   const identifier::Table &from,
1652
 
                   const identifier::Table &to)
 
3056
mysql_rename_table(handlerton *base, const char *old_db,
 
3057
                   const char *old_name, const char *new_db,
 
3058
                   const char *new_name, uint flags)
1653
3059
{
1654
 
  int error= 0;
1655
 
 
1656
 
  assert(base);
1657
 
 
1658
 
  if (not plugin::StorageEngine::doesSchemaExist(to))
1659
 
  {
1660
 
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1661
 
    return true;
1662
 
  }
1663
 
 
1664
 
  error= base->renameTable(session, from, to);
1665
 
 
 
3060
  THD *thd= current_thd;
 
3061
  char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
 
3062
  char *from_base= from, *to_base= to;
 
3063
  char tmp_name[NAME_LEN+1];
 
3064
  handler *file;
 
3065
  int error=0;
 
3066
 
 
3067
  file= (base == NULL ? 0 :
 
3068
         get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
 
3069
 
 
3070
  build_table_filename(from, sizeof(from), old_db, old_name, "",
 
3071
                       flags & FN_FROM_IS_TMP);
 
3072
  build_table_filename(to, sizeof(to), new_db, new_name, "",
 
3073
                       flags & FN_TO_IS_TMP);
 
3074
 
 
3075
  /*
 
3076
    If lower_case_table_names == 2 (case-preserving but case-insensitive
 
3077
    file system) and the storage is not HA_FILE_BASED, we need to provide
 
3078
    a lowercase file name, but we leave the .frm in mixed case.
 
3079
   */
 
3080
  if (lower_case_table_names == 2 && file &&
 
3081
      !(file->ha_table_flags() & HA_FILE_BASED))
 
3082
  {
 
3083
    strmov(tmp_name, old_name);
 
3084
    my_casedn_str(files_charset_info, tmp_name);
 
3085
    build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
 
3086
                         flags & FN_FROM_IS_TMP);
 
3087
    from_base= lc_from;
 
3088
 
 
3089
    strmov(tmp_name, new_name);
 
3090
    my_casedn_str(files_charset_info, tmp_name);
 
3091
    build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
 
3092
                         flags & FN_TO_IS_TMP);
 
3093
    to_base= lc_to;
 
3094
  }
 
3095
  if (!file || !(error=file->ha_rename_table(from_base, to_base)))
 
3096
  {
 
3097
    if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
 
3098
    {
 
3099
      error=my_errno;
 
3100
      /* Restore old file name */
 
3101
      if (file)
 
3102
        file->ha_rename_table(to_base, from_base);
 
3103
    }
 
3104
  }
 
3105
  delete file;
1666
3106
  if (error == HA_ERR_WRONG_COMMAND)
1667
 
  {
1668
 
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1669
 
  }
 
3107
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
1670
3108
  else if (error)
1671
 
  {
1672
 
    std::string from_path;
1673
 
    std::string to_path;
1674
 
 
1675
 
    from.getSQLPath(from_path);
1676
 
    to.getSQLPath(to_path);
1677
 
 
1678
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1679
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1680
 
 
1681
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1682
 
  }
1683
 
 
1684
 
  return error ? true : false; 
 
3109
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
 
3110
  return(error != 0);
1685
3111
}
1686
3112
 
1687
3113
 
1690
3116
 
1691
3117
  SYNOPSIS
1692
3118
    wait_while_table_is_used()
1693
 
    session                     Thread Cursor
 
3119
    thd                 Thread handler
1694
3120
    table               Table to remove from cache
1695
3121
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
1696
3122
                        HA_EXTRA_FORCE_REOPEN if table is not be used
1700
3126
   the table is closed.
1701
3127
 
1702
3128
  PREREQUISITES
1703
 
    Lock on table::Cache::singleton().mutex()
 
3129
    Lock on LOCK_open
1704
3130
    Win32 clients must also have a WRITE LOCK on the table !
1705
3131
*/
1706
3132
 
1707
 
void wait_while_table_is_used(Session *session, Table *table,
 
3133
void wait_while_table_is_used(THD *thd, TABLE *table,
1708
3134
                              enum ha_extra_function function)
1709
3135
{
1710
3136
 
1711
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
3137
  safe_mutex_assert_owner(&LOCK_open);
1712
3138
 
1713
 
  table->cursor->extra(function);
 
3139
  VOID(table->file->extra(function));
1714
3140
  /* Mark all tables that are in use as 'old' */
1715
 
  session->abortLock(table);    /* end threads waiting on lock */
 
3141
  mysql_lock_abort(thd, table, true);   /* end threads waiting on lock */
1716
3142
 
1717
3143
  /* Wait until all there are no other threads that has this table open */
1718
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1719
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
3144
  remove_table_from_cache(thd, table->s->db.str,
 
3145
                          table->s->table_name.str,
 
3146
                          RTFC_WAIT_OTHER_THREAD_FLAG);
 
3147
  return;
1720
3148
}
1721
3149
 
1722
3150
/*
1724
3152
 
1725
3153
  SYNOPSIS
1726
3154
    close_cached_table()
1727
 
    session                     Thread Cursor
 
3155
    thd                 Thread handler
1728
3156
    table               Table to remove from cache
1729
3157
 
1730
3158
  NOTES
1732
3160
    reopen the table.
1733
3161
 
1734
3162
  PREREQUISITES
1735
 
    Lock on table::Cache::singleton().mutex()
 
3163
    Lock on LOCK_open
1736
3164
    Win32 clients must also have a WRITE LOCK on the table !
1737
3165
*/
1738
3166
 
1739
 
void Session::close_cached_table(Table *table)
 
3167
void close_cached_table(THD *thd, TABLE *table)
1740
3168
{
1741
3169
 
1742
 
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
 
3170
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
1743
3171
  /* Close lock if this is not got with LOCK TABLES */
1744
 
  if (lock)
 
3172
  if (thd->lock)
1745
3173
  {
1746
 
    unlockTables(lock);
1747
 
    lock= NULL;                 // Start locked threads
 
3174
    mysql_unlock_tables(thd, thd->lock);
 
3175
    thd->lock=0;                        // Start locked threads
1748
3176
  }
1749
3177
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1750
 
  unlink_open_table(table);
1751
 
 
1752
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1753
 
  locking::broadcast_refresh();
1754
 
}
 
3178
  unlink_open_table(thd, table, true);
 
3179
 
 
3180
  /* When lock on LOCK_open is freed other threads can continue */
 
3181
  broadcast_refresh();
 
3182
  return;
 
3183
}
 
3184
 
 
3185
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
 
3186
                             const char* operator_name, const char* errmsg)
 
3187
 
 
3188
{
 
3189
  Protocol *protocol= thd->protocol;
 
3190
  protocol->prepare_for_resend();
 
3191
  protocol->store(table->alias, system_charset_info);
 
3192
  protocol->store((char*) operator_name, system_charset_info);
 
3193
  protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3194
  protocol->store(errmsg, system_charset_info);
 
3195
  thd->clear_error();
 
3196
  if (protocol->write())
 
3197
    return -1;
 
3198
  return 1;
 
3199
}
 
3200
 
 
3201
 
 
3202
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
 
3203
                              HA_CHECK_OPT *check_opt)
 
3204
{
 
3205
  int error= 0;
 
3206
  TABLE tmp_table, *table;
 
3207
  TABLE_SHARE *share;
 
3208
  char from[FN_REFLEN],tmp[FN_REFLEN+32];
 
3209
  const char **ext;
 
3210
  struct stat stat_info;
 
3211
 
 
3212
  if (!(check_opt->sql_flags & TT_USEFRM))
 
3213
    return(0);
 
3214
 
 
3215
  if (!(table= table_list->table))              /* if open_ltable failed */
 
3216
  {
 
3217
    char key[MAX_DBKEY_LENGTH];
 
3218
    uint key_length;
 
3219
 
 
3220
    key_length= create_table_def_key(thd, key, table_list, 0);
 
3221
    pthread_mutex_lock(&LOCK_open);
 
3222
    if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
 
3223
                                  &error))))
 
3224
    {
 
3225
      pthread_mutex_unlock(&LOCK_open);
 
3226
      return(0);                                // Can't open frm file
 
3227
    }
 
3228
 
 
3229
    if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
 
3230
    {
 
3231
      release_table_share(share, RELEASE_NORMAL);
 
3232
      pthread_mutex_unlock(&LOCK_open);
 
3233
      return(0);                           // Out of memory
 
3234
    }
 
3235
    table= &tmp_table;
 
3236
    pthread_mutex_unlock(&LOCK_open);
 
3237
  }
 
3238
 
 
3239
  /*
 
3240
    REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
 
3241
  */
 
3242
  if (table->s->tmp_table)
 
3243
  {
 
3244
    error= send_check_errmsg(thd, table_list, "repair",
 
3245
                             "Cannot repair temporary table from .frm file");
 
3246
    goto end;
 
3247
  }
 
3248
 
 
3249
  /*
 
3250
    User gave us USE_FRM which means that the header in the index file is
 
3251
    trashed.
 
3252
    In this case we will try to fix the table the following way:
 
3253
    - Rename the data file to a temporary name
 
3254
    - Truncate the table
 
3255
    - Replace the new data file with the old one
 
3256
    - Run a normal repair using the new index file and the old data file
 
3257
  */
 
3258
 
 
3259
  /*
 
3260
    Check if this is a table type that stores index and data separately,
 
3261
    like ISAM or MyISAM. We assume fixed order of engine file name
 
3262
    extentions array. First element of engine file name extentions array
 
3263
    is meta/index file extention. Second element - data file extention. 
 
3264
  */
 
3265
  ext= table->file->bas_ext();
 
3266
  if (!ext[0] || !ext[1])
 
3267
    goto end;                                   // No data file
 
3268
 
 
3269
  // Name of data file
 
3270
  strxmov(from, table->s->normalized_path.str, ext[1], NullS);
 
3271
  if (stat(from, &stat_info))
 
3272
    goto end;                           // Can't use USE_FRM flag
 
3273
 
 
3274
  snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
 
3275
           from, current_pid, thd->thread_id);
 
3276
 
 
3277
  /* If we could open the table, close it */
 
3278
  if (table_list->table)
 
3279
  {
 
3280
    pthread_mutex_lock(&LOCK_open);
 
3281
    close_cached_table(thd, table);
 
3282
    pthread_mutex_unlock(&LOCK_open);
 
3283
  }
 
3284
  if (lock_and_wait_for_table_name(thd,table_list))
 
3285
  {
 
3286
    error= -1;
 
3287
    goto end;
 
3288
  }
 
3289
  if (my_rename(from, tmp, MYF(MY_WME)))
 
3290
  {
 
3291
    pthread_mutex_lock(&LOCK_open);
 
3292
    unlock_table_name(thd, table_list);
 
3293
    pthread_mutex_unlock(&LOCK_open);
 
3294
    error= send_check_errmsg(thd, table_list, "repair",
 
3295
                             "Failed renaming data file");
 
3296
    goto end;
 
3297
  }
 
3298
  if (mysql_truncate(thd, table_list, 1))
 
3299
  {
 
3300
    pthread_mutex_lock(&LOCK_open);
 
3301
    unlock_table_name(thd, table_list);
 
3302
    pthread_mutex_unlock(&LOCK_open);
 
3303
    error= send_check_errmsg(thd, table_list, "repair",
 
3304
                             "Failed generating table from .frm file");
 
3305
    goto end;
 
3306
  }
 
3307
  if (my_rename(tmp, from, MYF(MY_WME)))
 
3308
  {
 
3309
    pthread_mutex_lock(&LOCK_open);
 
3310
    unlock_table_name(thd, table_list);
 
3311
    pthread_mutex_unlock(&LOCK_open);
 
3312
    error= send_check_errmsg(thd, table_list, "repair",
 
3313
                             "Failed restoring .MYD file");
 
3314
    goto end;
 
3315
  }
 
3316
 
 
3317
  /*
 
3318
    Now we should be able to open the partially repaired table
 
3319
    to finish the repair in the handler later on.
 
3320
  */
 
3321
  pthread_mutex_lock(&LOCK_open);
 
3322
  if (reopen_name_locked_table(thd, table_list, true))
 
3323
  {
 
3324
    unlock_table_name(thd, table_list);
 
3325
    pthread_mutex_unlock(&LOCK_open);
 
3326
    error= send_check_errmsg(thd, table_list, "repair",
 
3327
                             "Failed to open partially repaired table");
 
3328
    goto end;
 
3329
  }
 
3330
  pthread_mutex_unlock(&LOCK_open);
 
3331
 
 
3332
end:
 
3333
  if (table == &tmp_table)
 
3334
  {
 
3335
    pthread_mutex_lock(&LOCK_open);
 
3336
    closefrm(table, 1);                         // Free allocated memory
 
3337
    pthread_mutex_unlock(&LOCK_open);
 
3338
  }
 
3339
  return(error);
 
3340
}
 
3341
 
 
3342
 
1755
3343
 
1756
3344
/*
1757
3345
  RETURN VALUES
1758
3346
    false Message sent to net (admin operation went ok)
1759
 
    true  Message should be sent by caller
 
3347
    true  Message should be sent by caller 
1760
3348
          (admin operation or network communication failed)
1761
3349
*/
1762
 
static bool admin_table(Session* session, TableList* tables,
 
3350
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
1763
3351
                              HA_CHECK_OPT* check_opt,
1764
3352
                              const char *operator_name,
1765
3353
                              thr_lock_type lock_type,
1766
3354
                              bool open_for_modify,
1767
 
                              int (Cursor::*operator_func)(Session *,
 
3355
                              bool no_warnings_for_error,
 
3356
                              uint extra_open_options,
 
3357
                              int (*prepare_func)(THD *, TABLE_LIST *,
 
3358
                                                  HA_CHECK_OPT *),
 
3359
                              int (handler::*operator_func)(THD *,
1768
3360
                                                            HA_CHECK_OPT *))
1769
3361
{
1770
 
  TableList *table;
1771
 
  Select_Lex *select= &session->getLex()->select_lex;
 
3362
  TABLE_LIST *table;
 
3363
  SELECT_LEX *select= &thd->lex->select_lex;
1772
3364
  List<Item> field_list;
1773
3365
  Item *item;
 
3366
  Protocol *protocol= thd->protocol;
 
3367
  LEX *lex= thd->lex;
1774
3368
  int result_code= 0;
1775
 
  TransactionServices &transaction_services= TransactionServices::singleton();
1776
 
  const CHARSET_INFO * const cs= system_charset_info;
1777
 
 
1778
 
  if (! session->endActiveTransaction())
1779
 
    return 1;
1780
 
 
 
3369
  CHARSET_INFO *cs= system_charset_info;
 
3370
 
 
3371
  if (end_active_trans(thd))
 
3372
    return(1);
1781
3373
  field_list.push_back(item = new Item_empty_string("Table",
1782
3374
                                                    NAME_CHAR_LEN * 2,
1783
3375
                                                    cs));
1788
3380
  item->maybe_null = 1;
1789
3381
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1790
3382
  item->maybe_null = 1;
1791
 
  if (session->getClient()->sendFields(&field_list))
1792
 
    return true;
 
3383
  if (protocol->send_fields(&field_list,
 
3384
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
3385
    return(true);
 
3386
 
 
3387
  mysql_ha_rm_tables(thd, tables, false);
1793
3388
 
1794
3389
  for (table= tables; table; table= table->next_local)
1795
3390
  {
1796
 
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
 
    std::string table_name;
 
3391
    char table_name[NAME_LEN*2+2];
 
3392
    char* db = table->db;
1798
3393
    bool fatal_error=0;
1799
3394
 
1800
 
    table_identifier.getSQLPath(table_name);
1801
 
 
 
3395
    strxmov(table_name, db, ".", table->table_name, NullS);
 
3396
    thd->open_options|= extra_open_options;
1802
3397
    table->lock_type= lock_type;
1803
3398
    /* open only one table from local list of command */
1804
3399
    {
1805
 
      TableList *save_next_global, *save_next_local;
 
3400
      TABLE_LIST *save_next_global, *save_next_local;
1806
3401
      save_next_global= table->next_global;
1807
3402
      table->next_global= 0;
1808
3403
      save_next_local= table->next_local;
1809
3404
      table->next_local= 0;
1810
 
      select->table_list.first= (unsigned char*)table;
 
3405
      select->table_list.first= (uchar*)table;
1811
3406
      /*
1812
3407
        Time zone tables and SP tables can be add to lex->query_tables list,
1813
3408
        so it have to be prepared.
1814
 
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
 
3409
        TODO: Investigate if we can put extra tables into argument instead of
 
3410
        using lex->query_tables
1815
3411
      */
1816
 
      session->getLex()->query_tables= table;
1817
 
      session->getLex()->query_tables_last= &table->next_global;
1818
 
      session->getLex()->query_tables_own_last= 0;
1819
 
      session->no_warnings_for_error= 0;
 
3412
      lex->query_tables= table;
 
3413
      lex->query_tables_last= &table->next_global;
 
3414
      lex->query_tables_own_last= 0;
 
3415
      thd->no_warnings_for_error= no_warnings_for_error;
 
3416
      table->required_type=FRMTYPE_TABLE;
1820
3417
 
1821
 
      session->openTablesLock(table);
1822
 
      session->no_warnings_for_error= 0;
 
3418
      open_and_lock_tables(thd, table);
 
3419
      thd->no_warnings_for_error= 0;
1823
3420
      table->next_global= save_next_global;
1824
3421
      table->next_local= save_next_local;
 
3422
      thd->open_options&= ~extra_open_options;
 
3423
    }
 
3424
 
 
3425
    if (prepare_func)
 
3426
    {
 
3427
      switch ((*prepare_func)(thd, table, check_opt)) {
 
3428
      case  1:           // error, message written to net
 
3429
        ha_autocommit_or_rollback(thd, 1);
 
3430
        end_trans(thd, ROLLBACK);
 
3431
        close_thread_tables(thd);
 
3432
        continue;
 
3433
      case -1:           // error, message could be written to net
 
3434
        /* purecov: begin inspected */
 
3435
        goto err;
 
3436
        /* purecov: end */
 
3437
      default:           // should be 0 otherwise
 
3438
        ;
 
3439
      }
1825
3440
    }
1826
3441
 
1827
3442
    /*
1828
 
      CHECK Table command is only command where VIEW allowed here and this
 
3443
      CHECK TABLE command is only command where VIEW allowed here and this
1829
3444
      command use only temporary teble method for VIEWs resolving => there
1830
3445
      can't be VIEW tree substitition of join view => if opening table
1831
 
      succeed then table->table will have real Table pointer as value (in
 
3446
      succeed then table->table will have real TABLE pointer as value (in
1832
3447
      case of join view substitution table->table can be 0, but here it is
1833
3448
      impossible)
1834
3449
    */
1835
3450
    if (!table->table)
1836
3451
    {
1837
 
      if (!session->warn_list.elements)
1838
 
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
3452
      if (!thd->warn_list.elements)
 
3453
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1839
3454
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1840
 
      result_code= HA_ADMIN_CORRUPT;
1841
3455
      goto send_result;
1842
3456
    }
1843
3457
 
1844
3458
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
1845
3459
    {
1846
 
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
 
      uint32_t length;
1848
 
      session->getClient()->store(table_name.c_str());
1849
 
      session->getClient()->store(operator_name);
1850
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
3460
      /* purecov: begin inspected */
 
3461
      char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
 
3462
      uint length;
 
3463
      protocol->prepare_for_resend();
 
3464
      protocol->store(table_name, system_charset_info);
 
3465
      protocol->store(operator_name, system_charset_info);
 
3466
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
1851
3467
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
 
                       table_name.c_str());
1853
 
      session->getClient()->store(buff, length);
1854
 
      transaction_services.autocommitOrRollback(*session, false);
1855
 
      session->endTransaction(COMMIT);
1856
 
      session->close_thread_tables();
1857
 
      session->getLex()->reset_query_tables_list(false);
 
3468
                       table_name);
 
3469
      protocol->store(buff, length, system_charset_info);
 
3470
      ha_autocommit_or_rollback(thd, 0);
 
3471
      end_trans(thd, COMMIT);
 
3472
      close_thread_tables(thd);
 
3473
      lex->reset_query_tables_list(false);
1858
3474
      table->table=0;                           // For query cache
1859
 
      if (session->getClient()->flush())
 
3475
      if (protocol->write())
1860
3476
        goto err;
1861
3477
      continue;
 
3478
      /* purecov: end */
1862
3479
    }
1863
3480
 
1864
3481
    /* Close all instances of the table to allow repair to rename files */
1865
 
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
 
3482
    if (lock_type == TL_WRITE && table->table->s->version)
1866
3483
    {
1867
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1868
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1869
 
                                                  "Waiting to get writelock");
1870
 
      session->abortLock(table->table);
1871
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1873
 
      session->exit_cond(old_message);
1874
 
      if (session->getKilled())
 
3484
      pthread_mutex_lock(&LOCK_open);
 
3485
      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 
3486
                                              "Waiting to get writelock");
 
3487
      mysql_lock_abort(thd,table->table, true);
 
3488
      remove_table_from_cache(thd, table->table->s->db.str,
 
3489
                              table->table->s->table_name.str,
 
3490
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
3491
                              RTFC_CHECK_KILLED_FLAG);
 
3492
      thd->exit_cond(old_message);
 
3493
      if (thd->killed)
1875
3494
        goto err;
1876
3495
      open_for_modify= 0;
1877
3496
    }
1878
3497
 
1879
 
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
 
3498
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
3499
    {
 
3500
      /* purecov: begin inspected */
 
3501
      protocol->prepare_for_resend();
 
3502
      protocol->store(table_name, system_charset_info);
 
3503
      protocol->store(operator_name, system_charset_info);
 
3504
      protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
 
3505
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
 
3506
                      system_charset_info);
 
3507
      if (protocol->write())
 
3508
        goto err;
 
3509
      /* purecov: end */
 
3510
    }
 
3511
 
 
3512
    if (operator_func == &handler::ha_repair &&
 
3513
        !(check_opt->sql_flags & TT_USEFRM))
 
3514
    {
 
3515
      if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
 
3516
          (table->table->file->ha_check_for_upgrade(check_opt) ==
 
3517
           HA_ADMIN_NEEDS_ALTER))
 
3518
      {
 
3519
        ha_autocommit_or_rollback(thd, 1);
 
3520
        close_thread_tables(thd);
 
3521
        tmp_disable_binlog(thd); // binlogging is done by caller if wanted
 
3522
        result_code= mysql_recreate_table(thd, table);
 
3523
        reenable_binlog(thd);
 
3524
        /*
 
3525
          mysql_recreate_table() can push OK or ERROR.
 
3526
          Clear 'OK' status. If there is an error, keep it:
 
3527
          we will store the error message in a result set row 
 
3528
          and then clear.
 
3529
        */
 
3530
        if (thd->main_da.is_ok())
 
3531
          thd->main_da.reset_diagnostics_area();
 
3532
        goto send_result;
 
3533
      }
 
3534
    }
 
3535
 
 
3536
    result_code = (table->table->file->*operator_func)(thd, check_opt);
1880
3537
 
1881
3538
send_result:
1882
3539
 
1883
 
    session->getLex()->cleanup_after_one_table_open();
1884
 
    session->clear_error();  // these errors shouldn't get client
 
3540
    lex->cleanup_after_one_table_open();
 
3541
    thd->clear_error();  // these errors shouldn't get client
1885
3542
    {
1886
 
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1887
 
      DRIZZLE_ERROR *err;
 
3543
      List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
 
3544
      MYSQL_ERROR *err;
1888
3545
      while ((err= it++))
1889
3546
      {
1890
 
        session->getClient()->store(table_name.c_str());
1891
 
        session->getClient()->store(operator_name);
1892
 
        session->getClient()->store(warning_level_names[err->level].str,
1893
 
                               warning_level_names[err->level].length);
1894
 
        session->getClient()->store(err->msg);
1895
 
        if (session->getClient()->flush())
 
3547
        protocol->prepare_for_resend();
 
3548
        protocol->store(table_name, system_charset_info);
 
3549
        protocol->store((char*) operator_name, system_charset_info);
 
3550
        protocol->store(warning_level_names[err->level].str,
 
3551
                        warning_level_names[err->level].length,
 
3552
                        system_charset_info);
 
3553
        protocol->store(err->msg, system_charset_info);
 
3554
        if (protocol->write())
1896
3555
          goto err;
1897
3556
      }
1898
 
      drizzle_reset_errors(session, true);
 
3557
      mysql_reset_errors(thd, true);
1899
3558
    }
1900
 
    session->getClient()->store(table_name.c_str());
1901
 
    session->getClient()->store(operator_name);
 
3559
    protocol->prepare_for_resend();
 
3560
    protocol->store(table_name, system_charset_info);
 
3561
    protocol->store(operator_name, system_charset_info);
 
3562
 
 
3563
send_result_message:
1902
3564
 
1903
3565
    switch (result_code) {
1904
3566
    case HA_ADMIN_NOT_IMPLEMENTED:
1905
3567
      {
1906
3568
        char buf[ERRMSGSIZE+20];
1907
 
        uint32_t length=snprintf(buf, ERRMSGSIZE,
 
3569
        uint length=snprintf(buf, ERRMSGSIZE,
1908
3570
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1910
 
        session->getClient()->store(buf, length);
 
3571
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
3572
        protocol->store(buf, length, system_charset_info);
 
3573
      }
 
3574
      break;
 
3575
 
 
3576
    case HA_ADMIN_NOT_BASE_TABLE:
 
3577
      {
 
3578
        char buf[ERRMSGSIZE+20];
 
3579
        uint length= snprintf(buf, ERRMSGSIZE,
 
3580
                              ER(ER_BAD_TABLE_ERROR), table_name);
 
3581
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
3582
        protocol->store(buf, length, system_charset_info);
1911
3583
      }
1912
3584
      break;
1913
3585
 
1914
3586
    case HA_ADMIN_OK:
1915
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1916
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
3587
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3588
      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
1917
3589
      break;
1918
3590
 
1919
3591
    case HA_ADMIN_FAILED:
1920
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1921
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
3592
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3593
      protocol->store(STRING_WITH_LEN("Operation failed"),
 
3594
                      system_charset_info);
1922
3595
      break;
1923
3596
 
1924
3597
    case HA_ADMIN_REJECT:
1925
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1926
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
3598
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3599
      protocol->store(STRING_WITH_LEN("Operation need committed state"),
 
3600
                      system_charset_info);
1927
3601
      open_for_modify= false;
1928
3602
      break;
1929
3603
 
1930
3604
    case HA_ADMIN_ALREADY_DONE:
1931
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1932
 
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
 
3605
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
 
3606
      protocol->store(STRING_WITH_LEN("Table is already up to date"),
 
3607
                      system_charset_info);
1933
3608
      break;
1934
3609
 
1935
3610
    case HA_ADMIN_CORRUPT:
1936
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1937
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
3611
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3612
      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
1938
3613
      fatal_error=1;
1939
3614
      break;
1940
3615
 
1941
3616
    case HA_ADMIN_INVALID:
1942
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1943
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1944
 
      break;
 
3617
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3618
      protocol->store(STRING_WITH_LEN("Invalid argument"),
 
3619
                      system_charset_info);
 
3620
      break;
 
3621
 
 
3622
    case HA_ADMIN_TRY_ALTER:
 
3623
    {
 
3624
      /*
 
3625
        This is currently used only by InnoDB. ha_innobase::optimize() answers
 
3626
        "try with alter", so here we close the table, do an ALTER TABLE,
 
3627
        reopen the table and do ha_innobase::analyze() on it.
 
3628
      */
 
3629
      ha_autocommit_or_rollback(thd, 0);
 
3630
      close_thread_tables(thd);
 
3631
      TABLE_LIST *save_next_local= table->next_local,
 
3632
                 *save_next_global= table->next_global;
 
3633
      table->next_local= table->next_global= 0;
 
3634
      tmp_disable_binlog(thd); // binlogging is done by caller if wanted
 
3635
      result_code= mysql_recreate_table(thd, table);
 
3636
      reenable_binlog(thd);
 
3637
      /*
 
3638
        mysql_recreate_table() can push OK or ERROR.
 
3639
        Clear 'OK' status. If there is an error, keep it:
 
3640
        we will store the error message in a result set row 
 
3641
        and then clear.
 
3642
      */
 
3643
      if (thd->main_da.is_ok())
 
3644
        thd->main_da.reset_diagnostics_area();
 
3645
      ha_autocommit_or_rollback(thd, 0);
 
3646
      close_thread_tables(thd);
 
3647
      if (!result_code) // recreation went ok
 
3648
      {
 
3649
        if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
 
3650
            ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
 
3651
          result_code= 0; // analyze went ok
 
3652
      }
 
3653
      if (result_code) // either mysql_recreate_table or analyze failed
 
3654
      {
 
3655
        assert(thd->is_error());
 
3656
        if (thd->is_error())
 
3657
        {
 
3658
          const char *err_msg= thd->main_da.message();
 
3659
          if (!thd->vio_ok())
 
3660
          {
 
3661
            sql_print_error(err_msg);
 
3662
          }
 
3663
          else
 
3664
          {
 
3665
            /* Hijack the row already in-progress. */
 
3666
            protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3667
            protocol->store(err_msg, system_charset_info);
 
3668
            (void)protocol->write();
 
3669
            /* Start off another row for HA_ADMIN_FAILED */
 
3670
            protocol->prepare_for_resend();
 
3671
            protocol->store(table_name, system_charset_info);
 
3672
            protocol->store(operator_name, system_charset_info);
 
3673
          }
 
3674
          thd->clear_error();
 
3675
        }
 
3676
      }
 
3677
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
 
3678
      table->next_local= save_next_local;
 
3679
      table->next_global= save_next_global;
 
3680
      goto send_result_message;
 
3681
    }
 
3682
    case HA_ADMIN_WRONG_CHECKSUM:
 
3683
    {
 
3684
      protocol->store(STRING_WITH_LEN("note"), system_charset_info);
 
3685
      protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
 
3686
                      system_charset_info);
 
3687
      break;
 
3688
    }
 
3689
 
 
3690
    case HA_ADMIN_NEEDS_UPGRADE:
 
3691
    case HA_ADMIN_NEEDS_ALTER:
 
3692
    {
 
3693
      char buf[ERRMSGSIZE];
 
3694
      uint length;
 
3695
 
 
3696
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3697
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
 
3698
      protocol->store(buf, length, system_charset_info);
 
3699
      fatal_error=1;
 
3700
      break;
 
3701
    }
1945
3702
 
1946
3703
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1947
3704
      {
1948
3705
        char buf[ERRMSGSIZE+20];
1949
 
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1950
 
                             _("Unknown - internal error %d during operation"),
 
3706
        uint length=snprintf(buf, ERRMSGSIZE,
 
3707
                             "Unknown - internal error %d during operation",
1951
3708
                             result_code);
1952
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1953
 
        session->getClient()->store(buf, length);
 
3709
        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
3710
        protocol->store(buf, length, system_charset_info);
1954
3711
        fatal_error=1;
1955
3712
        break;
1956
3713
      }
1958
3715
    if (table->table)
1959
3716
    {
1960
3717
      if (fatal_error)
1961
 
      {
1962
 
        table->table->getMutableShare()->resetVersion();               // Force close of table
1963
 
      }
 
3718
        table->table->s->version=0;               // Force close of table
1964
3719
      else if (open_for_modify)
1965
3720
      {
1966
 
        if (table->table->getShare()->getType())
1967
 
        {
1968
 
          table->table->cursor->info(HA_STATUS_CONST);
1969
 
        }
 
3721
        if (table->table->s->tmp_table)
 
3722
          table->table->file->info(HA_STATUS_CONST);
1970
3723
        else
1971
3724
        {
1972
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
3725
          pthread_mutex_lock(&LOCK_open);
 
3726
          remove_table_from_cache(thd, table->table->s->db.str,
 
3727
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
 
3728
          pthread_mutex_unlock(&LOCK_open);
1975
3729
        }
1976
3730
      }
1977
3731
    }
1978
 
    transaction_services.autocommitOrRollback(*session, false);
1979
 
    session->endTransaction(COMMIT);
1980
 
    session->close_thread_tables();
 
3732
    ha_autocommit_or_rollback(thd, 0);
 
3733
    end_trans(thd, COMMIT);
 
3734
    close_thread_tables(thd);
1981
3735
    table->table=0;                             // For query cache
1982
 
    if (session->getClient()->flush())
 
3736
    if (protocol->write())
1983
3737
      goto err;
1984
3738
  }
1985
3739
 
1986
 
  session->my_eof();
 
3740
  my_eof(thd);
1987
3741
  return(false);
1988
3742
 
1989
3743
err:
1990
 
  transaction_services.autocommitOrRollback(*session, true);
1991
 
  session->endTransaction(ROLLBACK);
1992
 
  session->close_thread_tables();                       // Shouldn't be needed
 
3744
  ha_autocommit_or_rollback(thd, 1);
 
3745
  end_trans(thd, ROLLBACK);
 
3746
  close_thread_tables(thd);                     // Shouldn't be needed
1993
3747
  if (table)
1994
3748
    table->table=0;
1995
3749
  return(true);
1996
3750
}
1997
3751
 
1998
 
  /*
1999
 
    Create a new table by copying from source table
2000
 
 
2001
 
    Altough exclusive name-lock on target table protects us from concurrent
2002
 
    DML and DDL operations on it we still want to wrap .FRM creation and call
2003
 
    to plugin::StorageEngine::createTable() in critical section protected by
2004
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2005
 
    disregard name-locks, like I_S implementation, for example. This is a
2006
 
    temporary and should not be copied. Instead we should fix our code to
2007
 
    always honor name-locks.
2008
 
 
2009
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2010
 
    during the call to plugin::StorageEngine::createTable().
2011
 
    See bug #28614 for more info.
2012
 
  */
2013
 
static bool create_table_wrapper(Session &session,
2014
 
                                 const message::Table& create_table_proto,
2015
 
                                 identifier::Table::const_reference destination_identifier,
2016
 
                                 identifier::Table::const_reference source_identifier,
2017
 
                                 bool is_engine_set)
2018
 
{
2019
 
  // We require an additional table message because during parsing we used
2020
 
  // a "new" message and it will not have all of the information that the
2021
 
  // source table message would have.
2022
 
  message::Table new_table_message;
2023
 
 
2024
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2025
 
 
2026
 
  if (not source_table_message)
2027
 
  {
2028
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2029
 
    return false;
2030
 
  }
2031
 
 
2032
 
  new_table_message.CopyFrom(*source_table_message);
2033
 
 
2034
 
  if (destination_identifier.isTmp())
2035
 
  {
2036
 
    new_table_message.set_type(message::Table::TEMPORARY);
2037
 
  }
2038
 
  else
2039
 
  {
2040
 
    new_table_message.set_type(message::Table::STANDARD);
2041
 
  }
2042
 
 
2043
 
  if (is_engine_set)
2044
 
  {
2045
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2046
 
  }
2047
 
 
2048
 
  { // We now do a selective copy of elements on to the new table.
2049
 
    new_table_message.set_name(create_table_proto.name());
2050
 
    new_table_message.set_schema(create_table_proto.schema());
2051
 
    new_table_message.set_catalog(create_table_proto.catalog());
2052
 
  }
2053
 
 
2054
 
  /* Fix names of foreign keys being added */
2055
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2056
 
  {
2057
 
    if (new_table_message.fk_constraint(j).has_name())
2058
 
    {
2059
 
      std::string name(new_table_message.name());
2060
 
      char number[20];
2061
 
 
2062
 
      name.append("_ibfk_");
2063
 
      snprintf(number, sizeof(number), "%d", j+1);
2064
 
      name.append(number);
2065
 
 
2066
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2067
 
      pfkey->set_name(name);
2068
 
    }
2069
 
  }
2070
 
 
2071
 
  /*
2072
 
    As mysql_truncate don't work on a new table at this stage of
2073
 
    creation, instead create the table directly (for both normal and temporary tables).
2074
 
  */
2075
 
  bool success= plugin::StorageEngine::createTable(session,
2076
 
                                                   destination_identifier,
2077
 
                                                   new_table_message);
2078
 
 
2079
 
  if (success && not destination_identifier.isTmp())
2080
 
  {
2081
 
    TransactionServices &transaction_services= TransactionServices::singleton();
2082
 
    transaction_services.createTable(session, new_table_message);
2083
 
  }
2084
 
 
2085
 
  return success;
2086
 
}
 
3752
 
 
3753
bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
3754
{
 
3755
  return(mysql_admin_table(thd, tables, check_opt,
 
3756
                                "repair", TL_WRITE, 1,
 
3757
                                test(check_opt->sql_flags & TT_USEFRM),
 
3758
                                HA_OPEN_FOR_REPAIR,
 
3759
                                &prepare_for_repair,
 
3760
                                &handler::ha_repair));
 
3761
}
 
3762
 
 
3763
 
 
3764
bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
3765
{
 
3766
  return(mysql_admin_table(thd, tables, check_opt,
 
3767
                                "optimize", TL_WRITE, 1,0,0,0,
 
3768
                                &handler::ha_optimize));
 
3769
}
 
3770
 
 
3771
 
 
3772
/*
 
3773
  Assigned specified indexes for a table into key cache
 
3774
 
 
3775
  SYNOPSIS
 
3776
    mysql_assign_to_keycache()
 
3777
    thd         Thread object
 
3778
    tables      Table list (one table only)
 
3779
 
 
3780
  RETURN VALUES
 
3781
   false ok
 
3782
   true  error
 
3783
*/
 
3784
 
 
3785
bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
 
3786
                             LEX_STRING *key_cache_name)
 
3787
{
 
3788
  HA_CHECK_OPT check_opt;
 
3789
  KEY_CACHE *key_cache;
 
3790
 
 
3791
  check_opt.init();
 
3792
  pthread_mutex_lock(&LOCK_global_system_variables);
 
3793
  if (!(key_cache= get_key_cache(key_cache_name)))
 
3794
  {
 
3795
    pthread_mutex_unlock(&LOCK_global_system_variables);
 
3796
    my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
 
3797
    return(true);
 
3798
  }
 
3799
  pthread_mutex_unlock(&LOCK_global_system_variables);
 
3800
  check_opt.key_cache= key_cache;
 
3801
  return(mysql_admin_table(thd, tables, &check_opt,
 
3802
                                "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
 
3803
                                0, 0, &handler::assign_to_keycache));
 
3804
}
 
3805
 
 
3806
 
 
3807
/*
 
3808
  Reassign all tables assigned to a key cache to another key cache
 
3809
 
 
3810
  SYNOPSIS
 
3811
    reassign_keycache_tables()
 
3812
    thd         Thread object
 
3813
    src_cache   Reference to the key cache to clean up
 
3814
    dest_cache  New key cache
 
3815
 
 
3816
  NOTES
 
3817
    This is called when one sets a key cache size to zero, in which
 
3818
    case we have to move the tables associated to this key cache to
 
3819
    the "default" one.
 
3820
 
 
3821
    One has to ensure that one never calls this function while
 
3822
    some other thread is changing the key cache. This is assured by
 
3823
    the caller setting src_cache->in_init before calling this function.
 
3824
 
 
3825
    We don't delete the old key cache as there may still be pointers pointing
 
3826
    to it for a while after this function returns.
 
3827
 
 
3828
 RETURN VALUES
 
3829
    0     ok
 
3830
*/
 
3831
 
 
3832
int reassign_keycache_tables(THD *thd __attribute__((__unused__)),
 
3833
                             KEY_CACHE *src_cache,
 
3834
                             KEY_CACHE *dst_cache)
 
3835
{
 
3836
  assert(src_cache != dst_cache);
 
3837
  assert(src_cache->in_init);
 
3838
  src_cache->param_buff_size= 0;                // Free key cache
 
3839
  ha_resize_key_cache(src_cache);
 
3840
  ha_change_key_cache(src_cache, dst_cache);
 
3841
  return(0);
 
3842
}
 
3843
 
 
3844
/**
 
3845
  @brief          Create frm file based on I_S table
 
3846
 
 
3847
  @param[in]      thd                      thread handler
 
3848
  @param[in]      schema_table             I_S table           
 
3849
  @param[in]      dst_path                 path where frm should be created
 
3850
  @param[in]      create_info              Create info
 
3851
 
 
3852
  @return         Operation status
 
3853
    @retval       0                        success
 
3854
    @retval       1                        error
 
3855
*/
 
3856
bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table,
 
3857
                                  char *dst_path, HA_CREATE_INFO *create_info)
 
3858
{
 
3859
  HA_CREATE_INFO local_create_info;
 
3860
  Alter_info alter_info;
 
3861
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
 
3862
  uint keys= schema_table->table->s->keys;
 
3863
  uint db_options= 0;
 
3864
 
 
3865
  bzero((char*) &local_create_info, sizeof(local_create_info));
 
3866
  local_create_info.db_type= schema_table->table->s->db_type();
 
3867
  local_create_info.row_type= schema_table->table->s->row_type;
 
3868
  local_create_info.default_table_charset=default_charset_info;
 
3869
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
3870
  schema_table->table->use_all_columns();
 
3871
  if (mysql_prepare_alter_table(thd, schema_table->table,
 
3872
                                &local_create_info, &alter_info))
 
3873
    return(1);
 
3874
  if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
 
3875
                                 tmp_table, &db_options,
 
3876
                                 schema_table->table->file,
 
3877
                                 &schema_table->table->s->key_info, &keys, 0))
 
3878
    return(1);
 
3879
  local_create_info.max_rows= 0;
 
3880
  if (mysql_create_frm(thd, dst_path, NullS, NullS,
 
3881
                       &local_create_info, alter_info.create_list,
 
3882
                       keys, schema_table->table->s->key_info,
 
3883
                       schema_table->table->file))
 
3884
    return(1);
 
3885
  return(0);
 
3886
}
 
3887
 
2087
3888
 
2088
3889
/*
2089
3890
  Create a table identical to the specified table
2090
3891
 
2091
3892
  SYNOPSIS
2092
 
    create_like_table()
2093
 
    session             Thread object
 
3893
    mysql_create_like_table()
 
3894
    thd         Thread object
2094
3895
    table       Table list element for target table
2095
3896
    src_table   Table list element for source table
2096
3897
    create_info Create info
2100
3901
    true  error
2101
3902
*/
2102
3903
 
2103
 
bool create_like_table(Session* session,
2104
 
                       identifier::Table::const_reference destination_identifier,
2105
 
                       identifier::Table::const_reference source_identifier,
2106
 
                       message::Table &create_table_proto,
2107
 
                       bool is_if_not_exists,
2108
 
                       bool is_engine_set)
 
3904
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
 
3905
                             HA_CREATE_INFO *create_info)
2109
3906
{
 
3907
  TABLE *name_lock= 0;
 
3908
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
 
3909
  uint dst_path_length;
 
3910
  char *db= table->db;
 
3911
  char *table_name= table->table_name;
 
3912
  int  err;
2110
3913
  bool res= true;
2111
 
  bool table_exists= false;
 
3914
  uint not_used;
 
3915
 
 
3916
 
 
3917
  /* CREATE TABLE ... LIKE is not allowed for views. */
 
3918
  src_table->required_type= FRMTYPE_TABLE;
2112
3919
 
2113
3920
  /*
 
3921
    By opening source table we guarantee that it exists and no concurrent
 
3922
    DDL operation will mess with it. Later we also take an exclusive
 
3923
    name-lock on target table name, which makes copying of .frm file,
 
3924
    call to ha_create_table() and binlogging atomic against concurrent DML
 
3925
    and DDL operations on target table. Thus by holding both these "locks"
 
3926
    we ensure that our statement is properly isolated from all concurrent
 
3927
    operations which matter.
 
3928
  */
 
3929
  if (open_tables(thd, &src_table, &not_used, 0))
 
3930
    return(true);
 
3931
 
 
3932
  strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
 
3933
 
 
3934
  /* 
2114
3935
    Check that destination tables does not exist. Note that its name
2115
3936
    was already checked when it was added to the table list.
2116
 
 
2117
 
    For temporary tables we don't aim to grab locks.
2118
 
  */
2119
 
  if (destination_identifier.isTmp())
2120
 
  {
2121
 
    if (session->find_temporary_table(destination_identifier))
2122
 
    {
2123
 
      table_exists= true;
2124
 
    }
2125
 
    else
2126
 
    {
2127
 
      bool was_created= create_table_wrapper(*session,
2128
 
                                             create_table_proto,
2129
 
                                             destination_identifier,
2130
 
                                             source_identifier,
2131
 
                                             is_engine_set);
2132
 
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2133
 
      {
2134
 
        (void) session->rm_temporary_table(destination_identifier, true);
2135
 
      }
2136
 
      else if (not session->open_temporary_table(destination_identifier))
2137
 
      {
2138
 
        // We created, but we can't open... also, a hack.
2139
 
        (void) session->rm_temporary_table(destination_identifier, true);
2140
 
      }
2141
 
      else
2142
 
      {
2143
 
        res= false;
2144
 
      }
2145
 
    }
2146
 
  }
2147
 
  else // Standard table which will require locks.
2148
 
  {
2149
 
    Table *name_lock= 0;
2150
 
 
2151
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2152
 
    {
2153
 
      if (name_lock)
2154
 
      {
2155
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2156
 
        session->unlink_open_table(name_lock);
2157
 
      }
2158
 
 
2159
 
      return res;
2160
 
    }
2161
 
 
2162
 
    if (not name_lock)
2163
 
    {
2164
 
      table_exists= true;
2165
 
    }
2166
 
    else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2167
 
    {
2168
 
      table_exists= true;
2169
 
    }
2170
 
    else // Otherwise we create the table
2171
 
    {
2172
 
      bool was_created;
2173
 
      {
2174
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
 
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
 
                                          source_identifier, is_engine_set);
2177
 
      }
2178
 
 
2179
 
      // So we blew the creation of the table, and we scramble to clean up
2180
 
      // anything that might have been created (read... it is a hack)
2181
 
      if (not was_created)
2182
 
      {
2183
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
2184
 
      } 
2185
 
      else
2186
 
      {
2187
 
        res= false;
2188
 
      }
2189
 
    }
2190
 
 
 
3937
  */
 
3938
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
3939
  {
 
3940
    if (find_temporary_table(thd, db, table_name))
 
3941
      goto table_exists;
 
3942
    dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
 
3943
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
 
3944
  }
 
3945
  else
 
3946
  {
 
3947
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
3948
      goto err;
 
3949
    if (!name_lock)
 
3950
      goto table_exists;
 
3951
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
 
3952
                                          db, table_name, reg_ext, 0);
 
3953
    if (!access(dst_path, F_OK))
 
3954
      goto table_exists;
 
3955
  }
 
3956
 
 
3957
  /*
 
3958
    Create a new table by copying from source table
 
3959
 
 
3960
    Altough exclusive name-lock on target table protects us from concurrent
 
3961
    DML and DDL operations on it we still want to wrap .FRM creation and call
 
3962
    to ha_create_table() in critical section protected by LOCK_open in order
 
3963
    to provide minimal atomicity against operations which disregard name-locks,
 
3964
    like I_S implementation, for example. This is a temporary and should not
 
3965
    be copied. Instead we should fix our code to always honor name-locks.
 
3966
 
 
3967
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
 
3968
    during the call to ha_create_table(). See bug #28614 for more info.
 
3969
  */
 
3970
  VOID(pthread_mutex_lock(&LOCK_open));
 
3971
  if (src_table->schema_table)
 
3972
  {
 
3973
    if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
 
3974
    {
 
3975
      VOID(pthread_mutex_unlock(&LOCK_open));
 
3976
      goto err;
 
3977
    }
 
3978
  }
 
3979
  else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
 
3980
  {
 
3981
    if (my_errno == ENOENT)
 
3982
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
3983
    else
 
3984
      my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
3985
    VOID(pthread_mutex_unlock(&LOCK_open));
 
3986
    goto err;
 
3987
  }
 
3988
 
 
3989
  /*
 
3990
    As mysql_truncate don't work on a new table at this stage of
 
3991
    creation, instead create the table directly (for both normal
 
3992
    and temporary tables).
 
3993
  */
 
3994
  dst_path[dst_path_length - reg_ext_length]= '\0';  // Remove .frm
 
3995
  if (thd->variables.keep_files_on_create)
 
3996
    create_info->options|= HA_CREATE_KEEP_FILES;
 
3997
  err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
 
3998
  VOID(pthread_mutex_unlock(&LOCK_open));
 
3999
 
 
4000
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
4001
  {
 
4002
    if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
 
4003
                                     OTM_OPEN))
 
4004
    {
 
4005
      (void) rm_temporary_table(create_info->db_type,
 
4006
                                dst_path, false); /* purecov: inspected */
 
4007
      goto err;     /* purecov: inspected */
 
4008
    }
 
4009
  }
 
4010
  else if (err)
 
4011
  {
 
4012
    (void) quick_rm_table(create_info->db_type, db,
 
4013
                          table_name, 0); /* purecov: inspected */
 
4014
    goto err;       /* purecov: inspected */
 
4015
  }
 
4016
 
 
4017
  /*
 
4018
    We have to write the query before we unlock the tables.
 
4019
  */
 
4020
  if (thd->current_stmt_binlog_row_based)
 
4021
  {
 
4022
    /*
 
4023
       Since temporary tables are not replicated under row-based
 
4024
       replication, CREATE TABLE ... LIKE ... needs special
 
4025
       treatement.  We have four cases to consider, according to the
 
4026
       following decision table:
 
4027
 
 
4028
           ==== ========= ========= ==============================
 
4029
           Case    Target    Source Write to binary log
 
4030
           ==== ========= ========= ==============================
 
4031
           1       normal    normal Original statement
 
4032
           2       normal temporary Generated statement
 
4033
           3    temporary    normal Nothing
 
4034
           4    temporary temporary Nothing
 
4035
           ==== ========= ========= ==============================
 
4036
    */
 
4037
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
4038
    {
 
4039
      if (src_table->table->s->tmp_table)               // Case 2
 
4040
      {
 
4041
        char buf[2048];
 
4042
        String query(buf, sizeof(buf), system_charset_info);
 
4043
        query.length(0);  // Have to zero it since constructor doesn't
 
4044
 
 
4045
 
 
4046
        /*
 
4047
          Here we open the destination table, on which we already have
 
4048
          name-lock. This is needed for store_create_info() to work.
 
4049
          The table will be closed by unlink_open_table() at the end
 
4050
          of this function.
 
4051
        */
 
4052
        table->table= name_lock;
 
4053
        VOID(pthread_mutex_lock(&LOCK_open));
 
4054
        if (reopen_name_locked_table(thd, table, false))
 
4055
        {
 
4056
          VOID(pthread_mutex_unlock(&LOCK_open));
 
4057
          goto err;
 
4058
        }
 
4059
        VOID(pthread_mutex_unlock(&LOCK_open));
 
4060
 
 
4061
        int result= store_create_info(thd, table, &query,
 
4062
                                               create_info);
 
4063
 
 
4064
        assert(result == 0); // store_create_info() always return 0
 
4065
        write_bin_log(thd, true, query.ptr(), query.length());
 
4066
      }
 
4067
      else                                      // Case 1
 
4068
        write_bin_log(thd, true, thd->query, thd->query_length);
 
4069
    }
 
4070
    /*
 
4071
      Case 3 and 4 does nothing under RBR
 
4072
    */
 
4073
  }
 
4074
  else
 
4075
    write_bin_log(thd, true, thd->query, thd->query_length);
 
4076
 
 
4077
  res= false;
 
4078
  goto err;
 
4079
 
 
4080
table_exists:
 
4081
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
4082
  {
 
4083
    char warn_buff[MYSQL_ERRMSG_SIZE];
 
4084
    snprintf(warn_buff, sizeof(warn_buff),
 
4085
             ER(ER_TABLE_EXISTS_ERROR), table_name);
 
4086
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
4087
                 ER_TABLE_EXISTS_ERROR,warn_buff);
 
4088
    res= false;
 
4089
  }
 
4090
  else
 
4091
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
4092
 
 
4093
err:
 
4094
  if (name_lock)
 
4095
  {
 
4096
    pthread_mutex_lock(&LOCK_open);
 
4097
    unlink_open_table(thd, name_lock, false);
 
4098
    pthread_mutex_unlock(&LOCK_open);
 
4099
  }
 
4100
  return(res);
 
4101
}
 
4102
 
 
4103
 
 
4104
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
4105
{
 
4106
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
4107
 
 
4108
  return(mysql_admin_table(thd, tables, check_opt,
 
4109
                                "analyze", lock_type, 1, 0, 0, 0,
 
4110
                                &handler::ha_analyze));
 
4111
}
 
4112
 
 
4113
 
 
4114
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
 
4115
{
 
4116
  thr_lock_type lock_type = TL_READ_NO_INSERT;
 
4117
 
 
4118
  return(mysql_admin_table(thd, tables, check_opt,
 
4119
                                "check", lock_type,
 
4120
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
 
4121
                                &handler::ha_check));
 
4122
}
 
4123
 
 
4124
 
 
4125
/* table_list should contain just one table */
 
4126
static int
 
4127
mysql_discard_or_import_tablespace(THD *thd,
 
4128
                                   TABLE_LIST *table_list,
 
4129
                                   enum tablespace_op_type tablespace_op)
 
4130
{
 
4131
  TABLE *table;
 
4132
  my_bool discard;
 
4133
  int error;
 
4134
 
 
4135
  /*
 
4136
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
 
4137
    ALTER TABLE
 
4138
  */
 
4139
 
 
4140
  thd_proc_info(thd, "discard_or_import_tablespace");
 
4141
 
 
4142
  discard= test(tablespace_op == DISCARD_TABLESPACE);
 
4143
 
 
4144
 /*
 
4145
   We set this flag so that ha_innobase::open and ::external_lock() do
 
4146
   not complain when we lock the table
 
4147
 */
 
4148
  thd->tablespace_op= true;
 
4149
  if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
 
4150
  {
 
4151
    thd->tablespace_op=false;
 
4152
    return(-1);
 
4153
  }
 
4154
 
 
4155
  error= table->file->ha_discard_or_import_tablespace(discard);
 
4156
 
 
4157
  thd_proc_info(thd, "end");
 
4158
 
 
4159
  if (error)
 
4160
    goto err;
 
4161
 
 
4162
  /* The ALTER TABLE is always in its own transaction */
 
4163
  error = ha_autocommit_or_rollback(thd, 0);
 
4164
  if (end_active_trans(thd))
 
4165
    error=1;
 
4166
  if (error)
 
4167
    goto err;
 
4168
  write_bin_log(thd, false, thd->query, thd->query_length);
 
4169
 
 
4170
err:
 
4171
  ha_autocommit_or_rollback(thd, error);
 
4172
  thd->tablespace_op=false;
 
4173
  
 
4174
  if (error == 0)
 
4175
  {
 
4176
    my_ok(thd);
 
4177
    return(0);
 
4178
  }
 
4179
 
 
4180
  table->file->print_error(error, MYF(0));
 
4181
    
 
4182
  return(-1);
 
4183
}
 
4184
 
 
4185
/**
 
4186
  Copy all changes detected by parser to the HA_ALTER_FLAGS
 
4187
*/
 
4188
 
 
4189
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
 
4190
{
 
4191
  uint flags= alter_info->flags;
 
4192
 
 
4193
  if (ALTER_ADD_COLUMN & flags)
 
4194
    *alter_flags|= HA_ADD_COLUMN;
 
4195
  if (ALTER_DROP_COLUMN & flags)
 
4196
    *alter_flags|= HA_DROP_COLUMN;
 
4197
  if (ALTER_RENAME & flags)
 
4198
    *alter_flags|= HA_RENAME_TABLE;
 
4199
  if (ALTER_CHANGE_COLUMN & flags)
 
4200
    *alter_flags|= HA_CHANGE_COLUMN;
 
4201
  if (ALTER_COLUMN_DEFAULT & flags)
 
4202
    *alter_flags|= HA_COLUMN_DEFAULT_VALUE;
 
4203
  if (ALTER_COLUMN_STORAGE & flags)
 
4204
    *alter_flags|= HA_COLUMN_STORAGE;
 
4205
  if (ALTER_COLUMN_FORMAT & flags)
 
4206
    *alter_flags|= HA_COLUMN_FORMAT;
 
4207
  if (ALTER_COLUMN_ORDER & flags)
 
4208
    *alter_flags|= HA_ALTER_COLUMN_ORDER;
 
4209
  if (ALTER_STORAGE & flags)
 
4210
    *alter_flags|= HA_ALTER_STORAGE;
 
4211
  if (ALTER_ROW_FORMAT & flags)
 
4212
    *alter_flags|= HA_ALTER_ROW_FORMAT;
 
4213
  if (ALTER_RECREATE & flags)
 
4214
    *alter_flags|= HA_RECREATE;
 
4215
  if (ALTER_FOREIGN_KEY & flags)
 
4216
    *alter_flags|= HA_ALTER_FOREIGN_KEY;
 
4217
}
 
4218
 
 
4219
 
 
4220
/**
 
4221
   @param       thd                Thread
 
4222
   @param       table              The original table.
 
4223
   @param       alter_info         Alter options, fields and keys for the new
 
4224
                                   table.
 
4225
   @param       create_info        Create options for the new table.
 
4226
   @param       order_num          Number of order list elements.
 
4227
   @param[out]  ha_alter_flags  Flags that indicate what will be changed
 
4228
   @param[out]  ha_alter_info      Data structures needed for on-line alter
 
4229
   @param[out]  table_changes      Information about particular change
 
4230
 
 
4231
   First argument 'table' contains information of the original
 
4232
   table, which includes all corresponding parts that the new
 
4233
   table has in arguments create_list, key_list and create_info.
 
4234
 
 
4235
   By comparing the changes between the original and new table
 
4236
   we can determine how much it has changed after ALTER TABLE
 
4237
   and whether we need to make a copy of the table, or just change
 
4238
   the .frm file.
 
4239
 
 
4240
   Mark any changes detected in the ha_alter_flags.
 
4241
 
 
4242
   If there are no data changes, but index changes, 'index_drop_buffer'
 
4243
   and/or 'index_add_buffer' are populated with offsets into
 
4244
   table->key_info or key_info_buffer respectively for the indexes
 
4245
   that need to be dropped and/or (re-)created.
 
4246
 
 
4247
   @retval true  error
 
4248
   @retval false success
 
4249
*/
 
4250
 
 
4251
static
 
4252
bool
 
4253
compare_tables(THD *thd,
 
4254
               TABLE *table,
 
4255
               Alter_info *alter_info,
 
4256
                           HA_CREATE_INFO *create_info,
 
4257
               uint order_num,
 
4258
               HA_ALTER_FLAGS *alter_flags,
 
4259
               HA_ALTER_INFO *ha_alter_info,
 
4260
               uint *table_changes)
 
4261
{
 
4262
  Field **f_ptr, *field;
 
4263
  uint table_changes_local= 0;
 
4264
  List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
 
4265
  Create_field *new_field;
 
4266
  KEY_PART_INFO *key_part;
 
4267
  KEY_PART_INFO *end;
 
4268
  /*
 
4269
    Remember if the new definition has new VARCHAR column;
 
4270
    create_info->varchar will be reset in mysql_prepare_create_table.
 
4271
  */
 
4272
  bool varchar= create_info->varchar;
 
4273
 
 
4274
  {
 
4275
    /*
 
4276
      Create a copy of alter_info.
 
4277
      To compare the new and old table definitions, we need to "prepare"
 
4278
      the new definition - transform it from parser output to a format
 
4279
      that describes the final table layout (all column defaults are
 
4280
      initialized, duplicate columns are removed). This is done by
 
4281
      mysql_prepare_create_table.  Unfortunately,
 
4282
      mysql_prepare_create_table performs its transformations
 
4283
      "in-place", that is, modifies the argument.  Since we would
 
4284
      like to keep compare_tables() idempotent (not altering any
 
4285
      of the arguments) we create a copy of alter_info here and
 
4286
      pass it to mysql_prepare_create_table, then use the result
 
4287
      to evaluate possibility of fast ALTER TABLE, and then
 
4288
      destroy the copy.
 
4289
    */
 
4290
    Alter_info tmp_alter_info(*alter_info, thd->mem_root);
 
4291
    THD *thd= table->in_use;
 
4292
    uint db_options= 0; /* not used */
 
4293
    /* Create the prepared information. */
 
4294
    if (mysql_prepare_create_table(thd, create_info,
 
4295
                                   &tmp_alter_info,
 
4296
                                   (table->s->tmp_table != NO_TMP_TABLE),
 
4297
                                   &db_options,
 
4298
                                   table->file,
 
4299
                                   &ha_alter_info->key_info_buffer,
 
4300
                                   &ha_alter_info->key_count,
 
4301
                                   /* select_field_count */ 0))
 
4302
      return(true);
 
4303
    /* Allocate result buffers. */
 
4304
    if (! (ha_alter_info->index_drop_buffer=
 
4305
           (uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
 
4306
        ! (ha_alter_info->index_add_buffer=
 
4307
           (uint*) thd->alloc(sizeof(uint) *
 
4308
                              tmp_alter_info.key_list.elements)))
 
4309
      return(true);
 
4310
  }
 
4311
  /*
 
4312
    First we setup ha_alter_flags based on what was detected
 
4313
    by parser
 
4314
  */
 
4315
  setup_ha_alter_flags(alter_info, alter_flags);
 
4316
 
 
4317
 
 
4318
  /*
 
4319
    Some very basic checks. If number of fields changes, or the
 
4320
    handler, we need to run full ALTER TABLE. In the future
 
4321
    new fields can be added and old dropped without copy, but
 
4322
    not yet.
 
4323
 
 
4324
    Test also that engine was not given during ALTER TABLE, or
 
4325
    we are force to run regular alter table (copy).
 
4326
    E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
 
4327
 
 
4328
    For the following ones we also want to run regular alter table:
 
4329
    ALTER TABLE tbl_name ORDER BY ..
 
4330
    ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
 
4331
 
 
4332
    At the moment we can't handle altering temporary tables without a copy.
 
4333
    We also test if OPTIMIZE TABLE was given and was mapped to alter table.
 
4334
    In that case we always do full copy.
 
4335
 
 
4336
    There was a bug prior to mysql-4.0.25. Number of null fields was
 
4337
    calculated incorrectly. As a result frm and data files gets out of
 
4338
    sync after fast alter table. There is no way to determine by which
 
4339
    mysql version (in 4.0 and 4.1 branches) table was created, thus we
 
4340
    disable fast alter table for all tables created by mysql versions
 
4341
    prior to 5.0 branch.
 
4342
    See BUG#6236.
 
4343
  */
 
4344
  if (table->s->fields != alter_info->create_list.elements ||
 
4345
      table->s->db_type() != create_info->db_type ||
 
4346
      table->s->tmp_table ||
 
4347
      create_info->used_fields & HA_CREATE_USED_ENGINE ||
 
4348
      create_info->used_fields & HA_CREATE_USED_CHARSET ||
 
4349
      create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
 
4350
      create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
 
4351
      (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
 
4352
      order_num ||
 
4353
      !table->s->mysql_version ||
 
4354
      (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
 
4355
  {
 
4356
    *table_changes= IS_EQUAL_NO;
 
4357
    /*
 
4358
      Check what has changed and set alter_flags
 
4359
    */
 
4360
    if (table->s->fields < alter_info->create_list.elements)
 
4361
      *alter_flags|= HA_ADD_COLUMN;
 
4362
    else if (table->s->fields > alter_info->create_list.elements)
 
4363
      *alter_flags|= HA_DROP_COLUMN;
 
4364
    if (create_info->db_type != table->s->db_type() ||
 
4365
        create_info->used_fields & HA_CREATE_USED_ENGINE)
 
4366
      *alter_flags|= HA_ALTER_STORAGE_ENGINE;
 
4367
    if (create_info->used_fields & HA_CREATE_USED_CHARSET)
 
4368
      *alter_flags|= HA_CHANGE_CHARACTER_SET;
 
4369
    if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
 
4370
      *alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
 
4371
    if (alter_info->flags & ALTER_RECREATE)
 
4372
      *alter_flags|= HA_RECREATE;
 
4373
    /* TODO check for ADD/DROP FOREIGN KEY */
 
4374
    if (alter_info->flags & ALTER_FOREIGN_KEY)
 
4375
      *alter_flags|=  HA_ALTER_FOREIGN_KEY;
 
4376
    if (!table->s->mysql_version ||
 
4377
        (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
 
4378
      *alter_flags|=  HA_ALTER_COLUMN_TYPE;
 
4379
  }
 
4380
  /*
 
4381
    Go through fields and check if the original ones are compatible
 
4382
    with new table.
 
4383
  */
 
4384
  for (f_ptr= table->field, new_field= new_field_it++;
 
4385
       (new_field && (field= *f_ptr));
 
4386
       f_ptr++, new_field= new_field_it++)
 
4387
  {
 
4388
    /* Make sure we have at least the default charset in use. */
 
4389
    if (!new_field->charset)
 
4390
      new_field->charset= create_info->default_table_charset;
 
4391
 
 
4392
    /* Don't pack rows in old tables if the user has requested this. */
 
4393
    if (create_info->row_type == ROW_TYPE_DYNAMIC ||
 
4394
        (new_field->flags & BLOB_FLAG) ||
 
4395
        (new_field->sql_type == MYSQL_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
 
4396
      create_info->table_options|= HA_OPTION_PACK_RECORD;
 
4397
 
 
4398
    /* Check how fields have been modified */
 
4399
    if (alter_info->flags & ALTER_CHANGE_COLUMN)
 
4400
    {
 
4401
      /* Evaluate changes bitmap and send to check_if_incompatible_data() */
 
4402
      if (!(table_changes_local= field->is_equal(new_field)))
 
4403
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
4404
 
 
4405
      /* Check if field was renamed */
 
4406
      field->flags&= ~FIELD_IS_RENAMED;
 
4407
      if (my_strcasecmp(system_charset_info,
 
4408
                        field->field_name,
 
4409
                        new_field->field_name))
 
4410
      {
 
4411
        field->flags|= FIELD_IS_RENAMED;
 
4412
        *alter_flags|= HA_ALTER_COLUMN_NAME;
 
4413
      }
 
4414
 
 
4415
      *table_changes&= table_changes_local;
 
4416
      if (table_changes_local == IS_EQUAL_PACK_LENGTH)
 
4417
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
 
4418
 
 
4419
      /* Check that NULL behavior is same for old and new fields */
 
4420
      if ((new_field->flags & NOT_NULL_FLAG) !=
 
4421
          (uint) (field->flags & NOT_NULL_FLAG))
 
4422
      {
 
4423
        *table_changes= IS_EQUAL_NO;
 
4424
        *alter_flags|= HA_ALTER_COLUMN_NULLABLE;
 
4425
      }
 
4426
    }
 
4427
 
 
4428
    /* Clear indexed marker */
 
4429
    field->flags&= ~FIELD_IN_ADD_INDEX;
 
4430
  }
 
4431
 
 
4432
  /*
 
4433
    Go through keys and check if the original ones are compatible
 
4434
    with new table.
 
4435
  */
 
4436
  KEY *table_key;
 
4437
  KEY *table_key_end= table->key_info + table->s->keys;
 
4438
  KEY *new_key;
 
4439
  KEY *new_key_end=
 
4440
       ha_alter_info->key_info_buffer + ha_alter_info->key_count;
 
4441
 
 
4442
  /*
 
4443
    Step through all keys of the old table and search matching new keys.
 
4444
  */
 
4445
  ha_alter_info->index_drop_count= 0;
 
4446
  ha_alter_info->index_add_count= 0;
 
4447
  for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
4448
  {
 
4449
    KEY_PART_INFO *table_part;
 
4450
    KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
 
4451
    KEY_PART_INFO *new_part;
 
4452
 
 
4453
    /* Search a new key with the same name. */
 
4454
    for (new_key= ha_alter_info->key_info_buffer;
 
4455
         new_key < new_key_end;
 
4456
         new_key++)
 
4457
    {
 
4458
      if (! strcmp(table_key->name, new_key->name))
 
4459
        break;
 
4460
    }
 
4461
    if (new_key >= new_key_end)
 
4462
    {
 
4463
      /* Key not found. Add the offset of the key to the drop buffer. */
 
4464
      ha_alter_info->index_drop_buffer
 
4465
           [ha_alter_info->index_drop_count++]=
 
4466
           table_key - table->key_info;
 
4467
      if (table_key->flags & HA_NOSAME)
 
4468
      {
 
4469
        /* Unique key. Check for "PRIMARY". */
 
4470
        if (! my_strcasecmp(system_charset_info,
 
4471
                            table_key->name, primary_key_name))
 
4472
          *alter_flags|= HA_DROP_PK_INDEX;
 
4473
        else
 
4474
          *alter_flags|= HA_DROP_UNIQUE_INDEX;
 
4475
      }
 
4476
      else
 
4477
        *alter_flags|= HA_DROP_INDEX;
 
4478
      *table_changes= IS_EQUAL_NO;
 
4479
      continue;
 
4480
    }
 
4481
 
 
4482
    /* Check that the key types are compatible between old and new tables. */
 
4483
    if ((table_key->algorithm != new_key->algorithm) ||
 
4484
        ((table_key->flags & HA_KEYFLAG_MASK) !=
 
4485
         (new_key->flags & HA_KEYFLAG_MASK)) ||
 
4486
        (table_key->key_parts != new_key->key_parts))
 
4487
    {
 
4488
      if (table_key->flags & HA_NOSAME)
 
4489
      {
 
4490
        // Unique key. Check for "PRIMARY".
 
4491
        if (! my_strcasecmp(system_charset_info,
 
4492
                            table_key->name, primary_key_name))
 
4493
          *alter_flags|= HA_ALTER_PK_INDEX;
 
4494
        else
 
4495
          *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
4496
      }
 
4497
      else
 
4498
        *alter_flags|= HA_ALTER_INDEX;
 
4499
      goto index_changed;
 
4500
    }
 
4501
 
 
4502
    /*
 
4503
      Check that the key parts remain compatible between the old and
 
4504
      new tables.
 
4505
    */
 
4506
    for (table_part= table_key->key_part, new_part= new_key->key_part;
 
4507
         table_part < table_part_end;
 
4508
         table_part++, new_part++)
 
4509
    {
 
4510
      /*
 
4511
        Key definition has changed if we are using a different field or
 
4512
        if the used key part length is different. We know that the fields
 
4513
        did not change. Comparing field numbers is sufficient.
 
4514
      */
 
4515
      if ((table_part->length != new_part->length) ||
 
4516
          (table_part->fieldnr - 1 != new_part->fieldnr))
 
4517
      {
 
4518
        if (table_key->flags & HA_NOSAME)
 
4519
        {
 
4520
          /* Unique key. Check for "PRIMARY" */
 
4521
          if (! my_strcasecmp(system_charset_info,
 
4522
                              table_key->name, primary_key_name))
 
4523
            *alter_flags|= HA_ALTER_PK_INDEX;
 
4524
          else
 
4525
            *alter_flags|= HA_ALTER_UNIQUE_INDEX;
 
4526
        }
 
4527
        else
 
4528
          *alter_flags|= HA_ALTER_INDEX;
 
4529
        goto index_changed;
 
4530
      }
 
4531
    }
 
4532
    continue;
 
4533
 
 
4534
  index_changed:
 
4535
    /* Key modified. Add the offset of the key to both buffers. */
 
4536
    ha_alter_info->index_drop_buffer
 
4537
         [ha_alter_info->index_drop_count++]=
 
4538
         table_key - table->key_info;
 
4539
    ha_alter_info->index_add_buffer
 
4540
         [ha_alter_info->index_add_count++]=
 
4541
         new_key - ha_alter_info->key_info_buffer;
 
4542
    key_part= new_key->key_part;
 
4543
    end= key_part + new_key->key_parts;
 
4544
    for(; key_part != end; key_part++)
 
4545
    {
 
4546
      /* Mark field to be part of new key */
 
4547
      if ((field= table->field[key_part->fieldnr]))
 
4548
        field->flags|= FIELD_IN_ADD_INDEX;
 
4549
    }
 
4550
    *table_changes= IS_EQUAL_NO;
 
4551
  }
 
4552
  /*end of for (; table_key < table_key_end;) */
 
4553
 
 
4554
  /*
 
4555
    Step through all keys of the new table and find matching old keys.
 
4556
  */
 
4557
  for (new_key= ha_alter_info->key_info_buffer;
 
4558
       new_key < new_key_end;
 
4559
       new_key++)
 
4560
  {
 
4561
    /* Search an old key with the same name. */
 
4562
    for (table_key= table->key_info; table_key < table_key_end; table_key++)
 
4563
    {
 
4564
      if (! strcmp(table_key->name, new_key->name))
 
4565
        break;
 
4566
    }
 
4567
    if (table_key >= table_key_end)
 
4568
    {
 
4569
      /* Key not found. Add the offset of the key to the add buffer. */
 
4570
      ha_alter_info->index_add_buffer
 
4571
           [ha_alter_info->index_add_count++]=
 
4572
           new_key - ha_alter_info->key_info_buffer;
 
4573
      key_part= new_key->key_part;
 
4574
      end= key_part + new_key->key_parts;
 
4575
      for(; key_part != end; key_part++)
 
4576
      {
 
4577
        /* Mark field to be part of new key */
 
4578
        if ((field= table->field[key_part->fieldnr]))
 
4579
          field->flags|= FIELD_IN_ADD_INDEX;
 
4580
      }
 
4581
      if (new_key->flags & HA_NOSAME)
 
4582
      {
 
4583
        /* Unique key. Check for "PRIMARY" */
 
4584
        if (! my_strcasecmp(system_charset_info,
 
4585
                            new_key->name, primary_key_name))
 
4586
          *alter_flags|= HA_ADD_PK_INDEX;
 
4587
        else
 
4588
        *alter_flags|= HA_ADD_UNIQUE_INDEX;
 
4589
      }
 
4590
      else
 
4591
        *alter_flags|= HA_ADD_INDEX;
 
4592
      *table_changes= IS_EQUAL_NO;
 
4593
    }
 
4594
  }
 
4595
 
 
4596
  return(false);
 
4597
}
 
4598
 
 
4599
 
 
4600
/*
 
4601
  Manages enabling/disabling of indexes for ALTER TABLE
 
4602
 
 
4603
  SYNOPSIS
 
4604
    alter_table_manage_keys()
 
4605
      table                  Target table
 
4606
      indexes_were_disabled  Whether the indexes of the from table
 
4607
                             were disabled
 
4608
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
 
4609
 
 
4610
  RETURN VALUES
 
4611
    false  OK
 
4612
    true   Error
 
4613
*/
 
4614
 
 
4615
static
 
4616
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
 
4617
                             enum enum_enable_or_disable keys_onoff)
 
4618
{
 
4619
  int error= 0;
 
4620
  switch (keys_onoff) {
 
4621
  case ENABLE:
 
4622
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4623
    break;
 
4624
  case LEAVE_AS_IS:
 
4625
    if (!indexes_were_disabled)
 
4626
      break;
 
4627
    /* fall-through: disabled indexes */
 
4628
  case DISABLE:
 
4629
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
4630
  }
 
4631
 
 
4632
  if (error == HA_ERR_WRONG_COMMAND)
 
4633
  {
 
4634
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
4635
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
4636
                        table->s->table_name.str);
 
4637
    error= 0;
 
4638
  } else if (error)
 
4639
    table->file->print_error(error, MYF(0));
 
4640
 
 
4641
  return(error);
 
4642
}
 
4643
 
 
4644
int create_temporary_table(THD *thd,
 
4645
                           TABLE *table,
 
4646
                           char *new_db,
 
4647
                           char *tmp_name,
 
4648
                           HA_CREATE_INFO *create_info,
 
4649
                           Alter_info *alter_info,
 
4650
                           bool db_changed)
 
4651
{
 
4652
  int error;
 
4653
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
 
4654
  handlerton *old_db_type, *new_db_type;
 
4655
  old_db_type= table->s->db_type();
 
4656
  new_db_type= create_info->db_type;
 
4657
  /*
 
4658
    Handling of symlinked tables:
 
4659
    If no rename:
 
4660
      Create new data file and index file on the same disk as the
 
4661
      old data and index files.
 
4662
      Copy data.
 
4663
      Rename new data file over old data file and new index file over
 
4664
      old index file.
 
4665
      Symlinks are not changed.
 
4666
 
 
4667
   If rename:
 
4668
      Create new data file and index file on the same disk as the
 
4669
      old data and index files.  Create also symlinks to point at
 
4670
      the new tables.
 
4671
      Copy data.
 
4672
      At end, rename intermediate tables, and symlinks to intermediate
 
4673
      table, to final table name.
 
4674
      Remove old table and old symlinks
 
4675
 
 
4676
    If rename is made to another database:
 
4677
      Create new tables in new database.
 
4678
      Copy data.
 
4679
      Remove old table and symlinks.
 
4680
  */
 
4681
  if (db_changed)               // Ignore symlink if db changed
 
4682
  {
 
4683
    if (create_info->index_file_name)
 
4684
    {
 
4685
      /* Fix index_file_name to have 'tmp_name' as basename */
 
4686
      strmov(index_file, tmp_name);
 
4687
      create_info->index_file_name=fn_same(index_file,
 
4688
                                           create_info->index_file_name,
 
4689
                                           1);
 
4690
    }
 
4691
    if (create_info->data_file_name)
 
4692
    {
 
4693
      /* Fix data_file_name to have 'tmp_name' as basename */
 
4694
      strmov(data_file, tmp_name);
 
4695
      create_info->data_file_name=fn_same(data_file,
 
4696
                                          create_info->data_file_name,
 
4697
                                          1);
 
4698
    }
 
4699
  }
 
4700
  else
 
4701
    create_info->data_file_name=create_info->index_file_name=0;
 
4702
 
 
4703
  /*
 
4704
    Create a table with a temporary name.
 
4705
    With create_info->frm_only == 1 this creates a .frm file only.
 
4706
    We don't log the statement, it will be logged later.
 
4707
  */
 
4708
  tmp_disable_binlog(thd);
 
4709
  error= mysql_create_table(thd, new_db, tmp_name,
 
4710
                            create_info, alter_info, 1, 0);
 
4711
  reenable_binlog(thd);
 
4712
 
 
4713
  return(error);
 
4714
}
 
4715
 
 
4716
/*
 
4717
  Create a temporary table that reflects what an alter table operation
 
4718
  will accomplish.
 
4719
 
 
4720
  SYNOPSIS
 
4721
    create_altered_table()
 
4722
      thd              Thread handle
 
4723
      table            The original table
 
4724
      create_info      Information from the parsing phase about new
 
4725
                       table properties.
 
4726
      alter_info       Lists of fields, keys to be changed, added
 
4727
                       or dropped.
 
4728
      db_change        Specifies if the table is moved to another database
 
4729
  RETURN
 
4730
    A temporary table with all changes
 
4731
    NULL if error
 
4732
  NOTES
 
4733
    The temporary table is created without storing it in any storage engine
 
4734
    and is opened only to get the table struct and frm file reference.
 
4735
*/
 
4736
TABLE *create_altered_table(THD *thd,
 
4737
                            TABLE *table,
 
4738
                            char *new_db,
 
4739
                            HA_CREATE_INFO *create_info,
 
4740
                            Alter_info *alter_info,
 
4741
                            bool db_change)
 
4742
{
 
4743
  int error;
 
4744
  HA_CREATE_INFO altered_create_info(*create_info);
 
4745
  TABLE *altered_table;
 
4746
  char tmp_name[80];
 
4747
  char path[FN_REFLEN];
 
4748
 
 
4749
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
 
4750
           tmp_file_prefix, current_pid, thd->thread_id);
 
4751
  /* Safety fix for InnoDB */
 
4752
  if (lower_case_table_names)
 
4753
    my_casedn_str(files_charset_info, tmp_name);
 
4754
  altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
 
4755
  altered_create_info.frm_only= 1;
 
4756
  if ((error= create_temporary_table(thd, table, new_db, tmp_name,
 
4757
                                     &altered_create_info,
 
4758
                                     alter_info, db_change)))
 
4759
  {
 
4760
    return(NULL);
 
4761
  };
 
4762
 
 
4763
  build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
4764
                       FN_IS_TMP);
 
4765
  altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
 
4766
                                      OTM_ALTER);
 
4767
  return(altered_table);
 
4768
 
 
4769
  return(NULL);
 
4770
}
 
4771
 
 
4772
 
 
4773
/*
 
4774
  Perform a fast or on-line alter table
 
4775
 
 
4776
  SYNOPSIS
 
4777
    mysql_fast_or_online_alter_table()
 
4778
      thd              Thread handle
 
4779
      table            The original table
 
4780
      altered_table    A temporary table showing how we will change table
 
4781
      create_info      Information from the parsing phase about new
 
4782
                       table properties.
 
4783
      alter_info       Storage place for data used during different phases
 
4784
      ha_alter_flags   Bitmask that shows what will be changed
 
4785
      keys_onoff       Specifies if keys are to be enabled/disabled
 
4786
  RETURN
 
4787
     0  OK
 
4788
    >0  An error occured during the on-line alter table operation
 
4789
    -1  Error when re-opening table
 
4790
  NOTES
 
4791
    If mysql_alter_table does not need to copy the table, it is
 
4792
    either a fast alter table where the storage engine does not
 
4793
    need to know about the change, only the frm will change,
 
4794
    or the storage engine supports performing the alter table
 
4795
    operation directly, on-line without mysql having to copy
 
4796
    the table.
 
4797
*/
 
4798
int mysql_fast_or_online_alter_table(THD *thd,
 
4799
                                     TABLE *table,
 
4800
                                     TABLE *altered_table,
 
4801
                                     HA_CREATE_INFO *create_info,
 
4802
                                     HA_ALTER_INFO *alter_info,
 
4803
                                     HA_ALTER_FLAGS *ha_alter_flags,
 
4804
                                     enum enum_enable_or_disable keys_onoff)
 
4805
{
 
4806
  int error= 0;
 
4807
  bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
 
4808
  TABLE *t_table;
 
4809
 
 
4810
  if (online)
 
4811
  {
 
4812
   /*
 
4813
      Tell the handler to prepare for the online alter
 
4814
    */
 
4815
    if ((error= table->file->alter_table_phase1(thd,
 
4816
                                                altered_table,
 
4817
                                                create_info,
 
4818
                                                alter_info,
 
4819
                                                ha_alter_flags)))
 
4820
    {
 
4821
      goto err;
 
4822
    }
 
4823
 
 
4824
    /*
 
4825
       Tell the storage engine to perform the online alter table
 
4826
       TODO: 
 
4827
       if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
 
4828
       we need to wrap the next call with a DDL lock.
 
4829
     */
 
4830
    if ((error= table->file->alter_table_phase2(thd,
 
4831
                                                altered_table,
 
4832
                                                create_info,
 
4833
                                                alter_info,
 
4834
                                                ha_alter_flags)))
 
4835
    {
 
4836
      goto err;
 
4837
    }
 
4838
  }
 
4839
  /*
 
4840
    The final .frm file is already created as a temporary file
 
4841
    and will be renamed to the original table name.
 
4842
  */
 
4843
  VOID(pthread_mutex_lock(&LOCK_open));
 
4844
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
4845
  alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
4846
                          keys_onoff);
 
4847
  close_data_files_and_morph_locks(thd,
 
4848
                                   table->pos_in_table_list->db,
 
4849
                                   table->pos_in_table_list->table_name);
 
4850
  if (mysql_rename_table(NULL,
 
4851
                         altered_table->s->db.str,
 
4852
                         altered_table->s->table_name.str,
 
4853
                         table->s->db.str,
 
4854
                         table->s->table_name.str, FN_FROM_IS_TMP))
 
4855
  {
 
4856
    error= 1;
 
4857
    VOID(pthread_mutex_unlock(&LOCK_open));
 
4858
    goto err;
 
4859
  }
 
4860
  broadcast_refresh();
 
4861
  VOID(pthread_mutex_unlock(&LOCK_open));
 
4862
 
 
4863
  /*
 
4864
    The ALTER TABLE is always in its own transaction.
 
4865
    Commit must not be called while LOCK_open is locked. It could call
 
4866
    wait_if_global_read_lock(), which could create a deadlock if called
 
4867
    with LOCK_open.
 
4868
  */
 
4869
  error= ha_autocommit_or_rollback(thd, 0);
 
4870
 
 
4871
  if (ha_commit(thd))
 
4872
    error=1;
 
4873
  if (error)
 
4874
    goto err;
 
4875
  if (online)
 
4876
  {
 
4877
    VOID(pthread_mutex_lock(&LOCK_open));
 
4878
    if (reopen_table(table))
 
4879
    {
 
4880
      error= -1;
 
4881
      goto err;
 
4882
    }
 
4883
    VOID(pthread_mutex_unlock(&LOCK_open));
 
4884
    t_table= table;
 
4885
 
 
4886
   /*
 
4887
      Tell the handler that the changed frm is on disk and table
 
4888
      has been re-opened
 
4889
   */
 
4890
    if ((error= t_table->file->alter_table_phase3(thd, t_table)))
 
4891
    {
 
4892
      goto err;
 
4893
    }
 
4894
 
 
4895
    /*
 
4896
      We are going to reopen table down on the road, so we have to restore
 
4897
      state of the TABLE object which we used for obtaining of handler
 
4898
      object to make it suitable for reopening.
 
4899
    */
 
4900
    assert(t_table == table);
 
4901
    table->open_placeholder= 1;
 
4902
    VOID(pthread_mutex_lock(&LOCK_open));
 
4903
    close_handle_and_leave_table_as_lock(table);
 
4904
    VOID(pthread_mutex_unlock(&LOCK_open));
 
4905
  }
 
4906
 
 
4907
 err:
 
4908
  if (error)
 
4909
    return(error);
 
4910
  return 0;
 
4911
}
 
4912
 
 
4913
 
 
4914
/**
 
4915
  Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
 
4916
 
 
4917
  This function transforms parse output of ALTER TABLE - lists of
 
4918
  columns and keys to add, drop or modify into, essentially,
 
4919
  CREATE TABLE definition - a list of columns and keys of the new
 
4920
  table. While doing so, it also performs some (bug not all)
 
4921
  semantic checks.
 
4922
 
 
4923
  This function is invoked when we know that we're going to
 
4924
  perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
 
4925
  is not possible, perhaps because the ALTER statement contains
 
4926
  instructions that require change in table data, not only in
 
4927
  table definition or indexes.
 
4928
 
 
4929
  @param[in,out]  thd         thread handle. Used as a memory pool
 
4930
                              and source of environment information.
 
4931
  @param[in]      table       the source table, open and locked
 
4932
                              Used as an interface to the storage engine
 
4933
                              to acquire additional information about
 
4934
                              the original table.
 
4935
  @param[in,out]  create_info A blob with CREATE/ALTER TABLE
 
4936
                              parameters
 
4937
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
 
4938
                              Originally create_info was used only in
 
4939
                              CREATE TABLE and alter_info only in ALTER TABLE.
 
4940
                              But since ALTER might end-up doing CREATE,
 
4941
                              this distinction is gone and we just carry
 
4942
                              around two structures.
 
4943
 
 
4944
  @return
 
4945
    Fills various create_info members based on information retrieved
 
4946
    from the storage engine.
 
4947
    Sets create_info->varchar if the table has a VARCHAR column.
 
4948
    Prepares alter_info->create_list and alter_info->key_list with
 
4949
    columns and keys of the new table.
 
4950
  @retval true   error, out of memory or a semantical error in ALTER
 
4951
                 TABLE instructions
 
4952
  @retval false  success
 
4953
*/
 
4954
 
 
4955
static bool
 
4956
mysql_prepare_alter_table(THD *thd, TABLE *table,
 
4957
                          HA_CREATE_INFO *create_info,
 
4958
                          Alter_info *alter_info)
 
4959
{
 
4960
  /* New column definitions are added here */
 
4961
  List<Create_field> new_create_list;
 
4962
  /* New key definitions are added here */
 
4963
  List<Key> new_key_list;
 
4964
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
 
4965
  List_iterator<Create_field> def_it(alter_info->create_list);
 
4966
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
 
4967
  List_iterator<Key> key_it(alter_info->key_list);
 
4968
  List_iterator<Create_field> find_it(new_create_list);
 
4969
  List_iterator<Create_field> field_it(new_create_list);
 
4970
  List<Key_part_spec> key_parts;
 
4971
  uint db_create_options= (table->s->db_create_options
 
4972
                           & ~(HA_OPTION_PACK_RECORD));
 
4973
  uint used_fields= create_info->used_fields;
 
4974
  KEY *key_info=table->key_info;
 
4975
  bool rc= true;
 
4976
 
 
4977
 
 
4978
  create_info->varchar= false;
 
4979
  /* Let new create options override the old ones */
 
4980
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
 
4981
    create_info->min_rows= table->s->min_rows;
 
4982
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
 
4983
    create_info->max_rows= table->s->max_rows;
 
4984
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
 
4985
    create_info->avg_row_length= table->s->avg_row_length;
 
4986
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
4987
    create_info->default_table_charset= table->s->table_charset;
 
4988
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
4989
    {
 
4990
    /* Table has an autoincrement, copy value to new table */
 
4991
    table->file->info(HA_STATUS_AUTO);
 
4992
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
 
4993
  }
 
4994
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
 
4995
    create_info->key_block_size= table->s->key_block_size;
 
4996
  if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
 
4997
    create_info->transactional= table->s->transactional;
 
4998
 
 
4999
  restore_record(table, s->default_values);     // Empty record for DEFAULT
 
5000
  Create_field *def;
 
5001
 
 
5002
    /*
 
5003
    First collect all fields from table which isn't in drop_list
 
5004
    */
 
5005
  Field **f_ptr,*field;
 
5006
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
 
5007
    {
 
5008
    if (field->type() == MYSQL_TYPE_STRING)
 
5009
      create_info->varchar= true;
 
5010
    /* Check if field should be dropped */
 
5011
    Alter_drop *drop;
 
5012
    drop_it.rewind();
 
5013
    while ((drop=drop_it++))
 
5014
    {
 
5015
      if (drop->type == Alter_drop::COLUMN &&
 
5016
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
 
5017
    {
 
5018
        /* Reset auto_increment value if it was dropped */
 
5019
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
 
5020
            !(used_fields & HA_CREATE_USED_AUTO))
 
5021
      {
 
5022
          create_info->auto_increment_value=0;
 
5023
          create_info->used_fields|=HA_CREATE_USED_AUTO;
 
5024
      }
 
5025
        break;
 
5026
    }
 
5027
  }
 
5028
    if (drop)
 
5029
      {
 
5030
      drop_it.remove();
 
5031
      continue;
 
5032
    }
 
5033
    /* Check if field is changed */
 
5034
    def_it.rewind();
 
5035
    while ((def=def_it++))
 
5036
    {
 
5037
      if (def->change &&
 
5038
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
 
5039
        break;
 
5040
    }
 
5041
    if (def)
 
5042
    {                                           // Field is changed
 
5043
      def->field=field;
 
5044
      if (!def->after)
 
5045
        {
 
5046
        new_create_list.push_back(def);
 
5047
        def_it.remove();
 
5048
        }
 
5049
      }
 
5050
      else
 
5051
      {
 
5052
      /*
 
5053
        This field was not dropped and not changed, add it to the list
 
5054
        for the new table.
 
5055
      */
 
5056
      def= new Create_field(field, field);
 
5057
      new_create_list.push_back(def);
 
5058
      alter_it.rewind();                        // Change default if ALTER
 
5059
      Alter_column *alter;
 
5060
      while ((alter=alter_it++))
 
5061
        {
 
5062
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
 
5063
          break;
 
5064
        }
 
5065
      if (alter)
 
5066
        {
 
5067
        if (def->sql_type == MYSQL_TYPE_BLOB)
 
5068
        {
 
5069
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
 
5070
          goto err;
 
5071
        }
 
5072
        if ((def->def=alter->def))              // Use new default
 
5073
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
 
5074
        else
 
5075
          def->flags|= NO_DEFAULT_VALUE_FLAG;
 
5076
        alter_it.remove();
 
5077
      }
 
5078
    }
 
5079
  }
 
5080
  def_it.rewind();
 
5081
  while ((def=def_it++))                        // Add new columns
 
5082
  {
 
5083
    if (def->change && ! def->field)
 
5084
    {
 
5085
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
5086
      goto err;
 
5087
    }
 
5088
      /*
 
5089
      Check that the DATE/DATETIME not null field we are going to add is
 
5090
      either has a default value or the '0000-00-00' is allowed by the
 
5091
      set sql mode.
 
5092
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
5093
      flag to allow ALTER TABLE only if the table to be altered is empty.
 
5094
      */
 
5095
    if ((def->sql_type == MYSQL_TYPE_NEWDATE ||
 
5096
         def->sql_type == MYSQL_TYPE_DATETIME) &&
 
5097
         !alter_info->datetime_field &&
 
5098
         !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
5099
         thd->variables.sql_mode & MODE_NO_ZERO_DATE)
 
5100
    {
 
5101
        alter_info->datetime_field= def;
 
5102
        alter_info->error_if_not_empty= true;
 
5103
    }
 
5104
    if (!def->after)
 
5105
      new_create_list.push_back(def);
 
5106
    else if (def->after == first_keyword)
 
5107
      new_create_list.push_front(def);
 
5108
    else
 
5109
    {
 
5110
      Create_field *find;
 
5111
      find_it.rewind();
 
5112
      while ((find=find_it++))                  // Add new columns
 
5113
      {
 
5114
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
 
5115
          break;
 
5116
  }
 
5117
      if (!find)
 
5118
  {
 
5119
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
5120
    goto err;
 
5121
  }
 
5122
      find_it.after(def);                       // Put element after this
 
5123
      /*
 
5124
        XXX: hack for Bug#28427.
 
5125
        If column order has changed, force OFFLINE ALTER TABLE
 
5126
        without querying engine capabilities.  If we ever have an
 
5127
        engine that supports online ALTER TABLE CHANGE COLUMN
 
5128
        <name> AFTER <name1> (Falcon?), this fix will effectively
 
5129
        disable the capability.
 
5130
        TODO: detect the situation in compare_tables, behave based
 
5131
        on engine capabilities.
 
5132
      */
 
5133
      if (alter_info->build_method == HA_BUILD_ONLINE)
 
5134
      {
 
5135
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
5136
        goto err;
 
5137
      }
 
5138
      alter_info->build_method= HA_BUILD_OFFLINE;
 
5139
    }
 
5140
  }
 
5141
  if (alter_info->alter_list.elements)
 
5142
  {
 
5143
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
 
5144
             alter_info->alter_list.head()->name, table->s->table_name.str);
 
5145
    goto err;
 
5146
    }
 
5147
  if (!new_create_list.elements)
 
5148
    {
 
5149
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
 
5150
               MYF(0));
 
5151
    goto err;
 
5152
    }
 
5153
 
 
5154
    /*
 
5155
    Collect all keys which isn't in drop list. Add only those
 
5156
    for which some fields exists.
 
5157
    */
 
5158
 
 
5159
  for (uint i=0 ; i < table->s->keys ; i++,key_info++)
 
5160
    {
 
5161
    char *key_name= key_info->name;
 
5162
    Alter_drop *drop;
 
5163
    drop_it.rewind();
 
5164
    while ((drop=drop_it++))
 
5165
      {
 
5166
      if (drop->type == Alter_drop::KEY &&
 
5167
          !my_strcasecmp(system_charset_info,key_name, drop->name))
 
5168
        break;
 
5169
      }
 
5170
    if (drop)
 
5171
        {
 
5172
      drop_it.remove();
 
5173
      continue;
 
5174
    }
 
5175
 
 
5176
    KEY_PART_INFO *key_part= key_info->key_part;
 
5177
    key_parts.empty();
 
5178
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
5179
    {
 
5180
      if (!key_part->field)
 
5181
        continue;                               // Wrong field (from UNIREG)
 
5182
      const char *key_part_name=key_part->field->field_name;
 
5183
      Create_field *cfield;
 
5184
      field_it.rewind();
 
5185
      while ((cfield=field_it++))
 
5186
    {
 
5187
        if (cfield->change)
 
5188
    {
 
5189
          if (!my_strcasecmp(system_charset_info, key_part_name,
 
5190
                             cfield->change))
 
5191
            break;
 
5192
        }
 
5193
        else if (!my_strcasecmp(system_charset_info,
 
5194
                                key_part_name, cfield->field_name))
 
5195
          break;
 
5196
      }
 
5197
      if (!cfield)
 
5198
        continue;                               // Field is removed
 
5199
      uint key_part_length=key_part->length;
 
5200
      if (cfield->field)                        // Not new field
 
5201
      {
 
5202
        /*
 
5203
          If the field can't have only a part used in a key according to its
 
5204
          new type, or should not be used partially according to its
 
5205
          previous type, or the field length is less than the key part
 
5206
          length, unset the key part length.
 
5207
 
 
5208
          We also unset the key part length if it is the same as the
 
5209
          old field's length, so the whole new field will be used.
 
5210
 
 
5211
          BLOBs may have cfield->length == 0, which is why we test it before
 
5212
          checking whether cfield->length < key_part_length (in chars).
 
5213
         */
 
5214
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
 
5215
            !Field::type_can_have_key_part(cfield->sql_type) ||
 
5216
            (cfield->field->field_length == key_part_length &&
 
5217
             !f_is_blob(key_part->key_type)) ||
 
5218
            (cfield->length && (cfield->length < key_part_length /
 
5219
                                key_part->field->charset()->mbmaxlen)))
 
5220
          key_part_length= 0;                   // Use whole field
 
5221
      }
 
5222
      key_part_length /= key_part->field->charset()->mbmaxlen;
 
5223
      key_parts.push_back(new Key_part_spec(cfield->field_name,
 
5224
                                            strlen(cfield->field_name),
 
5225
                                            key_part_length));
 
5226
    }
 
5227
    if (key_parts.elements)
 
5228
    {
 
5229
      KEY_CREATE_INFO key_create_info;
 
5230
      Key *key;
 
5231
      enum Key::Keytype key_type;
 
5232
      bzero((char*) &key_create_info, sizeof(key_create_info));
 
5233
 
 
5234
      key_create_info.algorithm= key_info->algorithm;
 
5235
      if (key_info->flags & HA_USES_BLOCK_SIZE)
 
5236
        key_create_info.block_size= key_info->block_size;
 
5237
      if (key_info->flags & HA_USES_COMMENT)
 
5238
        key_create_info.comment= key_info->comment;
 
5239
 
 
5240
      if (key_info->flags & HA_NOSAME)
 
5241
      {
 
5242
        if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
 
5243
          key_type= Key::PRIMARY;
 
5244
        else
 
5245
          key_type= Key::UNIQUE;
 
5246
      }
 
5247
      else
 
5248
        key_type= Key::MULTIPLE;
 
5249
 
 
5250
      key= new Key(key_type, key_name, strlen(key_name),
 
5251
                   &key_create_info,
 
5252
                   test(key_info->flags & HA_GENERATED_KEY),
 
5253
                   key_parts);
 
5254
      new_key_list.push_back(key);
 
5255
    }
 
5256
  }
 
5257
  {
 
5258
    Key *key;
 
5259
    while ((key=key_it++))                      // Add new keys
 
5260
    {
 
5261
      if (key->type != Key::FOREIGN_KEY)
 
5262
        new_key_list.push_back(key);
 
5263
      if (key->name.str &&
 
5264
          !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
 
5265
      {
 
5266
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
 
5267
        goto err;
 
5268
      }
 
5269
    }
 
5270
  }
 
5271
 
 
5272
  if (alter_info->drop_list.elements)
 
5273
  {
 
5274
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
5275
             alter_info->drop_list.head()->name);
 
5276
    goto err;
 
5277
  }
 
5278
  if (alter_info->alter_list.elements)
 
5279
  {
 
5280
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
 
5281
             alter_info->alter_list.head()->name);
 
5282
    goto err;
 
5283
  }
 
5284
 
 
5285
  if (!create_info->comment.str)
 
5286
  {
 
5287
    create_info->comment.str= table->s->comment.str;
 
5288
    create_info->comment.length= table->s->comment.length;
 
5289
  }
 
5290
 
 
5291
  table->file->update_create_info(create_info);
 
5292
  if ((create_info->table_options &
 
5293
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
 
5294
      (used_fields & HA_CREATE_USED_PACK_KEYS))
 
5295
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
 
5296
  if (create_info->table_options &
 
5297
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
 
5298
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
 
5299
  if (create_info->table_options &
 
5300
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
 
5301
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
 
5302
                          HA_OPTION_NO_DELAY_KEY_WRITE);
 
5303
  create_info->table_options|= db_create_options;
 
5304
 
 
5305
  if (table->s->tmp_table)
 
5306
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
 
5307
 
 
5308
  rc= false;
 
5309
  alter_info->create_list.swap(new_create_list);
 
5310
  alter_info->key_list.swap(new_key_list);
 
5311
err:
 
5312
  return(rc);
 
5313
}
 
5314
 
 
5315
 
 
5316
/*
 
5317
  Alter table
 
5318
 
 
5319
  SYNOPSIS
 
5320
    mysql_alter_table()
 
5321
      thd              Thread handle
 
5322
      new_db           If there is a RENAME clause
 
5323
      new_name         If there is a RENAME clause
 
5324
      create_info      Information from the parsing phase about new
 
5325
                       table properties.
 
5326
      table_list       The table to change.
 
5327
      alter_info       Lists of fields, keys to be changed, added
 
5328
                       or dropped.
 
5329
      order_num        How many ORDER BY fields has been specified.
 
5330
      order            List of fields to ORDER BY.
 
5331
      ignore           Whether we have ALTER IGNORE TABLE
 
5332
 
 
5333
  DESCRIPTION
 
5334
    This is a veery long function and is everything but the kitchen sink :)
 
5335
    It is used to alter a table and not only by ALTER TABLE but also
 
5336
    CREATE|DROP INDEX are mapped on this function.
 
5337
 
 
5338
    When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
 
5339
    or both, then this function short cuts its operation by renaming
 
5340
    the table and/or enabling/disabling the keys. In this case, the FRM is
 
5341
    not changed, directly by mysql_alter_table. However, if there is a
 
5342
    RENAME + change of a field, or an index, the short cut is not used.
 
5343
    See how `create_list` is used to generate the new FRM regarding the
 
5344
    structure of the fields. The same is done for the indices of the table.
 
5345
 
 
5346
    Important is the fact, that this function tries to do as little work as
 
5347
    possible, by finding out whether a intermediate table is needed to copy
 
5348
    data into and when finishing the altering to use it as the original table.
 
5349
    For this reason the function compare_tables() is called, which decides
 
5350
    based on all kind of data how similar are the new and the original
 
5351
    tables.
 
5352
 
 
5353
  RETURN VALUES
 
5354
    false  OK
 
5355
    true   Error
 
5356
*/
 
5357
 
 
5358
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
 
5359
                       HA_CREATE_INFO *create_info,
 
5360
                       TABLE_LIST *table_list,
 
5361
                       Alter_info *alter_info,
 
5362
                       uint order_num, ORDER *order, bool ignore)
 
5363
{
 
5364
  TABLE *table, *new_table=0, *name_lock= 0;;
 
5365
  int error= 0;
 
5366
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
 
5367
  char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
 
5368
  char path[FN_REFLEN];
 
5369
  ha_rows copied= 0,deleted= 0;
 
5370
  handlerton *old_db_type, *new_db_type, *save_old_db_type;
 
5371
  legacy_db_type table_type;
 
5372
  frm_type_enum frm_type;
 
5373
 
 
5374
  if (table_list && table_list->schema_table)
 
5375
  {
 
5376
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
5377
    return(true);
 
5378
  }
 
5379
 
 
5380
  /*
 
5381
    Assign variables table_name, new_name, db, new_db, path
 
5382
    to simplify further comparisons: we want to see if it's a RENAME
 
5383
    later just by comparing the pointers, avoiding the need for strcmp.
 
5384
  */
 
5385
  thd_proc_info(thd, "init");
 
5386
  table_name=table_list->table_name;
 
5387
  alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
 
5388
  db=table_list->db;
 
5389
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
 
5390
    new_db= db;
 
5391
  build_table_filename(path, sizeof(path), db, table_name, "", 0);
 
5392
 
 
5393
  mysql_ha_rm_tables(thd, table_list, false);
 
5394
 
 
5395
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
 
5396
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
5397
    /* Conditionally writes to binlog. */
 
5398
    return(mysql_discard_or_import_tablespace(thd,table_list,
 
5399
                                              alter_info->tablespace_op));
 
5400
  strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, 
 
5401
           "/", table_name, reg_ext, NullS);
 
5402
  (void) unpack_filename(new_name_buff, new_name_buff);
 
5403
  /*
 
5404
    If this is just a rename of a view, short cut to the
 
5405
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
5406
    2) unlock LOCK_open.
 
5407
    This is a copy-paste added to make sure
 
5408
    ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
 
5409
    as an independent branch in mysql_execute_command. The need
 
5410
    for a copy-paste arose because the main code flow of ALTER TABLE
 
5411
    ... RENAME tries to use open_ltable, which does not work for views
 
5412
    (open_ltable was never modified to merge table lists of child tables
 
5413
    into the main table list, like open_tables does).
 
5414
    This code is wrong and will be removed, please do not copy.
 
5415
  */
 
5416
  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
 
5417
 
 
5418
  if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
 
5419
    return(true);
 
5420
  table->use_all_columns();
 
5421
 
 
5422
  /*
 
5423
    Prohibit changing of the UNION list of a non-temporary MERGE table
 
5424
    under LOCK tables. It would be quite difficult to reuse a shrinked
 
5425
    set of tables from the old table or to open a new TABLE object for
 
5426
    an extended list and verify that they belong to locked tables.
 
5427
  */
 
5428
  if (thd->locked_tables &&
 
5429
      (create_info->used_fields & HA_CREATE_USED_UNION) &&
 
5430
      (table->s->tmp_table == NO_TMP_TABLE))
 
5431
  {
 
5432
    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
 
5433
    return(true);
 
5434
  }
 
5435
 
 
5436
  /* Check that we are not trying to rename to an existing table */
 
5437
  if (new_name)
 
5438
  {
 
5439
    strmov(new_name_buff,new_name);
 
5440
    strmov(new_alias= new_alias_buff, new_name);
 
5441
    if (lower_case_table_names)
 
5442
    {
 
5443
      if (lower_case_table_names != 2)
 
5444
      {
 
5445
        my_casedn_str(files_charset_info, new_name_buff);
 
5446
        new_alias= new_name;                    // Create lower case table name
 
5447
      }
 
5448
      my_casedn_str(files_charset_info, new_name);
 
5449
    }
 
5450
    if (new_db == db &&
 
5451
        !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
5452
    {
 
5453
      /*
 
5454
        Source and destination table names are equal: make later check
 
5455
        easier.
 
5456
      */
 
5457
      new_alias= new_name= table_name;
 
5458
    }
 
5459
    else
 
5460
    {
 
5461
      if (table->s->tmp_table != NO_TMP_TABLE)
 
5462
      {
 
5463
        if (find_temporary_table(thd,new_db,new_name_buff))
 
5464
        {
 
5465
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
5466
          return(true);
 
5467
        }
 
5468
      }
 
5469
      else
 
5470
      {
 
5471
        if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
 
5472
          return(true);
 
5473
        if (!name_lock)
 
5474
        {
 
5475
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
5476
          return(true);
 
5477
        }
 
5478
 
 
5479
        build_table_filename(new_name_buff, sizeof(new_name_buff),
 
5480
                             new_db, new_name_buff, reg_ext, 0);
 
5481
        if (!access(new_name_buff, F_OK))
 
5482
        {
 
5483
          /* Table will be closed in do_command() */
 
5484
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
5485
          goto err;
 
5486
        }
 
5487
      }
 
5488
    }
 
5489
  }
 
5490
  else
 
5491
  {
 
5492
    new_alias= (lower_case_table_names == 2) ? alias : table_name;
 
5493
    new_name= table_name;
 
5494
  }
 
5495
 
 
5496
  old_db_type= table->s->db_type();
 
5497
  if (!create_info->db_type)
 
5498
  {
 
5499
    create_info->db_type= old_db_type;
 
5500
  }
 
5501
 
 
5502
  if (check_engine(thd, new_name, create_info))
 
5503
    goto err;
 
5504
  new_db_type= create_info->db_type;
 
5505
 
 
5506
  if (new_db_type != old_db_type ||
 
5507
      !table->file->can_switch_engines())
 
5508
  {
 
5509
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
 
5510
    goto err;
 
5511
  }
 
5512
 
 
5513
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
5514
    create_info->row_type= table->s->row_type;
 
5515
 
 
5516
  if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
 
5517
      ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
 
5518
  {
 
5519
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
5520
    goto err;
 
5521
  }
 
5522
 
 
5523
  thd_proc_info(thd, "setup");
 
5524
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
 
5525
      !table->s->tmp_table) // no need to touch frm
 
5526
  {
 
5527
    switch (alter_info->keys_onoff) {
 
5528
    case LEAVE_AS_IS:
 
5529
      break;
 
5530
    case ENABLE:
 
5531
      /*
 
5532
        wait_while_table_is_used() ensures that table being altered is
 
5533
        opened only by this thread and that TABLE::TABLE_SHARE::version
 
5534
        of TABLE object corresponding to this table is 0.
 
5535
        The latter guarantees that no DML statement will open this table
 
5536
        until ALTER TABLE finishes (i.e. until close_thread_tables())
 
5537
        while the fact that the table is still open gives us protection
 
5538
        from concurrent DDL statements.
 
5539
      */
 
5540
      VOID(pthread_mutex_lock(&LOCK_open));
 
5541
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
5542
      VOID(pthread_mutex_unlock(&LOCK_open));
 
5543
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
5544
      /* COND_refresh will be signaled in close_thread_tables() */
 
5545
      break;
 
5546
    case DISABLE:
 
5547
      VOID(pthread_mutex_lock(&LOCK_open));
 
5548
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
5549
      VOID(pthread_mutex_unlock(&LOCK_open));
 
5550
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
5551
      /* COND_refresh will be signaled in close_thread_tables() */
 
5552
      break;
 
5553
    default:
 
5554
      assert(false);
 
5555
      error= 0;
 
5556
      break;
 
5557
    }
 
5558
    if (error == HA_ERR_WRONG_COMMAND)
 
5559
    {
 
5560
      error= 0;
 
5561
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
5562
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
5563
                          table->alias);
 
5564
    }
 
5565
 
 
5566
    VOID(pthread_mutex_lock(&LOCK_open));
 
5567
    /*
 
5568
      Unlike to the above case close_cached_table() below will remove ALL
 
5569
      instances of TABLE from table cache (it will also remove table lock
 
5570
      held by this thread). So to make actual table renaming and writing
 
5571
      to binlog atomic we have to put them into the same critical section
 
5572
      protected by LOCK_open mutex. This also removes gap for races between
 
5573
      access() and mysql_rename_table() calls.
 
5574
    */
 
5575
 
 
5576
    if (!error && (new_name != table_name || new_db != db))
 
5577
    {
 
5578
      thd_proc_info(thd, "rename");
 
5579
      /*
 
5580
        Then do a 'simple' rename of the table. First we need to close all
 
5581
        instances of 'source' table.
 
5582
      */
 
5583
      close_cached_table(thd, table);
 
5584
      /*
 
5585
        Then, we want check once again that target table does not exist.
 
5586
        Actually the order of these two steps does not matter since
 
5587
        earlier we took name-lock on the target table, so we do them
 
5588
        in this particular order only to be consistent with 5.0, in which
 
5589
        we don't take this name-lock and where this order really matters.
 
5590
        TODO: Investigate if we need this access() check at all.
 
5591
      */
 
5592
      if (!access(new_name_buff,F_OK))
 
5593
      {
 
5594
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
5595
        error= -1;
 
5596
      }
 
5597
      else
 
5598
      {
 
5599
        *fn_ext(new_name)=0;
 
5600
        if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
 
5601
          error= -1;
 
5602
        else if (0)
 
5603
      {
 
5604
          VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
 
5605
                                  table_name, 0));
 
5606
          error= -1;
 
5607
      }
 
5608
    }
 
5609
  }
 
5610
 
 
5611
    if (error == HA_ERR_WRONG_COMMAND)
 
5612
  {
 
5613
      error= 0;
 
5614
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
5615
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
5616
                          table->alias);
 
5617
  }
 
5618
 
 
5619
    if (!error)
 
5620
    {
 
5621
      write_bin_log(thd, true, thd->query, thd->query_length);
 
5622
      my_ok(thd);
 
5623
  }
 
5624
    else if (error > 0)
 
5625
  {
 
5626
      table->file->print_error(error, MYF(0));
 
5627
      error= -1;
 
5628
    }
2191
5629
    if (name_lock)
2192
 
    {
2193
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2194
 
      session->unlink_open_table(name_lock);
2195
 
    }
2196
 
  }
2197
 
 
2198
 
  if (table_exists)
2199
 
  {
2200
 
    if (is_if_not_exists)
2201
 
    {
2202
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
 
      snprintf(warn_buff, sizeof(warn_buff),
2204
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2205
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2207
 
      return false;
2208
 
    }
2209
 
 
2210
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2211
 
 
 
5630
      unlink_open_table(thd, name_lock, false);
 
5631
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5632
    table_list->table= NULL;                    // For query cache
 
5633
    return(error);
 
5634
  }
 
5635
 
 
5636
  /* We have to do full alter table. */
 
5637
 
 
5638
    /*
 
5639
    If the old table had partitions and we are doing ALTER TABLE ...
 
5640
    engine= <new_engine>, the new table must preserve the original
 
5641
    partitioning. That means that the new engine is still the
 
5642
    partitioning engine, not the engine specified in the parser.
 
5643
    This is discovered  in prep_alter_part_table, which in such case
 
5644
    updates create_info->db_type.
 
5645
    Now we need to update the stack copy of create_info->db_type,
 
5646
    as otherwise we won't be able to correctly move the files of the
 
5647
    temporary table to the result table files.
 
5648
  */
 
5649
  new_db_type= create_info->db_type;
 
5650
 
 
5651
  if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
 
5652
      goto err;
 
5653
 
 
5654
  set_table_default_charset(thd, create_info, db);
 
5655
 
 
5656
 
 
5657
  if (thd->variables.old_alter_table
 
5658
      || (table->s->db_type() != create_info->db_type)
 
5659
     )
 
5660
  {
 
5661
    if (alter_info->build_method == HA_BUILD_ONLINE)
 
5662
    {
 
5663
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
5664
      goto err;
 
5665
    }
 
5666
    alter_info->build_method= HA_BUILD_OFFLINE;
 
5667
  }
 
5668
 
 
5669
  if (alter_info->build_method != HA_BUILD_OFFLINE)
 
5670
  {
 
5671
    TABLE *altered_table= 0;
 
5672
    HA_ALTER_INFO ha_alter_info;
 
5673
    HA_ALTER_FLAGS ha_alter_flags;
 
5674
    uint table_changes= IS_EQUAL_YES;
 
5675
    bool need_copy_table= true;
 
5676
    /* Check how much the tables differ. */
 
5677
    if (compare_tables(thd, table, alter_info,
 
5678
                       create_info, order_num,
 
5679
                       &ha_alter_flags,
 
5680
                       &ha_alter_info,
 
5681
                       &table_changes))
 
5682
    {
 
5683
      return(true);
 
5684
    }
 
5685
 
 
5686
    /*
 
5687
      Check if storage engine supports altering the table
 
5688
      on-line.
 
5689
    */
 
5690
 
 
5691
 
 
5692
    /*
 
5693
      If table is not renamed, changed database and
 
5694
      some change was detected then check if engine
 
5695
      can do the change on-line
 
5696
    */
 
5697
    if (new_name == table_name && new_db == db &&
 
5698
        ha_alter_flags.is_set())
 
5699
    {
 
5700
      Alter_info tmp_alter_info(*alter_info, thd->mem_root);
 
5701
 
 
5702
      /*
 
5703
        If no table rename,
 
5704
        check if table can be altered on-line
 
5705
      */
 
5706
      if (!(altered_table= create_altered_table(thd,
 
5707
                                                table,
 
5708
                                                new_db,
 
5709
                                                create_info,
 
5710
                                                &tmp_alter_info,
 
5711
                                                !strcmp(db, new_db))))
 
5712
        goto err;
 
5713
 
 
5714
      switch (table->file->check_if_supported_alter(altered_table,
 
5715
                                                    create_info,
 
5716
                                                    &ha_alter_flags,
 
5717
                                                    table_changes)) {
 
5718
      case HA_ALTER_SUPPORTED_WAIT_LOCK:
 
5719
      case HA_ALTER_SUPPORTED_NO_LOCK:
 
5720
        /*
 
5721
          @todo: Currently we always acquire an exclusive name
 
5722
          lock on the table metadata when performing fast or online
 
5723
          ALTER TABLE. In future we may consider this unnecessary,
 
5724
          and narrow the scope of the exclusive name lock to only
 
5725
          cover manipulation with .frms. Storage engine API
 
5726
          call check_if_supported_alter has provision for this
 
5727
          already now.
 
5728
        */
 
5729
        need_copy_table= false;
 
5730
        break;
 
5731
      case HA_ALTER_NOT_SUPPORTED:
 
5732
        if (alter_info->build_method == HA_BUILD_ONLINE)
 
5733
        {
 
5734
          my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
 
5735
          close_temporary_table(thd, altered_table, 1, 1);
 
5736
          goto err;
 
5737
        }
 
5738
        need_copy_table= true;
 
5739
        break;
 
5740
      case HA_ALTER_ERROR:
 
5741
      default:
 
5742
        close_temporary_table(thd, altered_table, 1, 1);
 
5743
        goto err;
 
5744
      }
 
5745
 
 
5746
    }
 
5747
    /* TODO need to check if changes can be handled as fast ALTER TABLE */
 
5748
    if (!altered_table)
 
5749
      need_copy_table= true;
 
5750
 
 
5751
    if (!need_copy_table)
 
5752
    {
 
5753
      error= mysql_fast_or_online_alter_table(thd,
 
5754
                                              table,
 
5755
                                              altered_table,
 
5756
                                              create_info,
 
5757
                                              &ha_alter_info,
 
5758
                                              &ha_alter_flags,
 
5759
                                              alter_info->keys_onoff);
 
5760
      if (thd->lock)
 
5761
      {
 
5762
        mysql_unlock_tables(thd, thd->lock);
 
5763
        thd->lock=0;
 
5764
      }
 
5765
      close_temporary_table(thd, altered_table, 1, 1);
 
5766
 
 
5767
      if (error)
 
5768
      {
 
5769
        switch (error) {
 
5770
        case(-1):
 
5771
          goto err_with_placeholders;
 
5772
        default:
 
5773
          goto err;
 
5774
        }
 
5775
      }
 
5776
      else
 
5777
      {
 
5778
        pthread_mutex_lock(&LOCK_open);
 
5779
        goto end_online;
 
5780
      }
 
5781
    }
 
5782
 
 
5783
    if (altered_table)
 
5784
      close_temporary_table(thd, altered_table, 1, 1);
 
5785
  }
 
5786
 
 
5787
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
 
5788
           current_pid, thd->thread_id);
 
5789
  /* Safety fix for innodb */
 
5790
  if (lower_case_table_names)
 
5791
    my_casedn_str(files_charset_info, tmp_name);
 
5792
 
 
5793
 
 
5794
  /* Create a temporary table with the new format */
 
5795
  if ((error= create_temporary_table(thd, table, new_db, tmp_name, 
 
5796
                                     create_info, alter_info, 
 
5797
                                     !strcmp(db, new_db))))
 
5798
  {
 
5799
    goto err;
 
5800
  }
 
5801
 
 
5802
  /* Open the table so we need to copy the data to it. */
 
5803
  if (table->s->tmp_table)
 
5804
  {
 
5805
    TABLE_LIST tbl;
 
5806
    bzero((void*) &tbl, sizeof(tbl));
 
5807
    tbl.db= new_db;
 
5808
    tbl.table_name= tbl.alias= tmp_name;
 
5809
    /* Table is in thd->temporary_tables */
 
5810
    new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
 
5811
                          MYSQL_LOCK_IGNORE_FLUSH);
 
5812
  }
 
5813
  else
 
5814
  {
 
5815
    char path[FN_REFLEN];
 
5816
    /* table is a normal table: Create temporary table in same directory */
 
5817
    build_table_filename(path, sizeof(path), new_db, tmp_name, "",
 
5818
                         FN_IS_TMP);
 
5819
    /* Open our intermediate table */
 
5820
    new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
 
5821
  }
 
5822
  if (!new_table)
 
5823
    goto err1;
 
5824
 
 
5825
  /* Copy the data if necessary. */
 
5826
  thd->count_cuted_fields= CHECK_FIELD_WARN;    // calc cuted fields
 
5827
  thd->cuted_fields=0L;
 
5828
  thd_proc_info(thd, "copy to tmp table");
 
5829
  copied=deleted=0;
 
5830
  /*
 
5831
    We do not copy data for MERGE tables. Only the children have data.
 
5832
    MERGE tables have HA_NO_COPY_ON_ALTER set.
 
5833
  */
 
5834
  if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
 
5835
  {
 
5836
    /* We don't want update TIMESTAMP fields during ALTER TABLE. */
 
5837
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
5838
    new_table->next_number_field=new_table->found_next_number_field;
 
5839
    error= copy_data_between_tables(table, new_table,
 
5840
                                    alter_info->create_list, ignore,
 
5841
                                   order_num, order, &copied, &deleted,
 
5842
                                    alter_info->keys_onoff,
 
5843
                                    alter_info->error_if_not_empty);
 
5844
  }
 
5845
  else
 
5846
  {
 
5847
    VOID(pthread_mutex_lock(&LOCK_open));
 
5848
    wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
5849
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5850
    alter_table_manage_keys(table, table->file->indexes_are_disabled(),
 
5851
                            alter_info->keys_onoff);
 
5852
    error= ha_autocommit_or_rollback(thd, 0);
 
5853
    if (end_active_trans(thd))
 
5854
      error= 1;
 
5855
  }
 
5856
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
5857
 
 
5858
  if (table->s->tmp_table != NO_TMP_TABLE)
 
5859
  {
 
5860
    /* We changed a temporary table */
 
5861
    if (error)
 
5862
      goto err1;
 
5863
    /* Close lock if this is a transactional table */
 
5864
    if (thd->lock)
 
5865
    {
 
5866
      mysql_unlock_tables(thd, thd->lock);
 
5867
      thd->lock=0;
 
5868
    }
 
5869
    /* Remove link to old table and rename the new one */
 
5870
    close_temporary_table(thd, table, 1, 1);
 
5871
    /* Should pass the 'new_name' as we store table name in the cache */
 
5872
    if (rename_temporary_table(thd, new_table, new_db, new_name))
 
5873
      goto err1;
 
5874
    /* We don't replicate alter table statement on temporary tables */
 
5875
    if (!thd->current_stmt_binlog_row_based)
 
5876
      write_bin_log(thd, true, thd->query, thd->query_length);
 
5877
    goto end_temporary;
 
5878
  }
 
5879
 
 
5880
  if (new_table)
 
5881
  {
 
5882
    /*
 
5883
      Close the intermediate table that will be the new table.
 
5884
      Note that MERGE tables do not have their children attached here.
 
5885
    */
 
5886
    intern_close_table(new_table);
 
5887
    my_free(new_table,MYF(0));
 
5888
  }
 
5889
  VOID(pthread_mutex_lock(&LOCK_open));
 
5890
  if (error)
 
5891
  {
 
5892
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
5893
    VOID(pthread_mutex_unlock(&LOCK_open));
 
5894
    goto err;
 
5895
  }
 
5896
 
 
5897
  /*
 
5898
    Data is copied. Now we:
 
5899
    1) Wait until all other threads close old version of table.
 
5900
    2) Close instances of table open by this thread and replace them
 
5901
       with exclusive name-locks.
 
5902
    3) Rename the old table to a temp name, rename the new one to the
 
5903
       old name.
 
5904
    4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
 
5905
       we reopen new version of table.
 
5906
    5) Write statement to the binary log.
 
5907
    6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
 
5908
       remove name-locks from list of open tables and table cache.
 
5909
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
5910
       call to remove name-locks from table cache and list of open table.
 
5911
  */
 
5912
 
 
5913
  thd_proc_info(thd, "rename result table");
 
5914
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
 
5915
           current_pid, thd->thread_id);
 
5916
  if (lower_case_table_names)
 
5917
    my_casedn_str(files_charset_info, old_name);
 
5918
 
 
5919
  wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
5920
  close_data_files_and_morph_locks(thd, db, table_name);
 
5921
 
 
5922
  error=0;
 
5923
  save_old_db_type= old_db_type;
 
5924
 
 
5925
  /*
 
5926
    This leads to the storage engine (SE) not being notified for renames in
 
5927
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
5928
    more. If we have an intermediate table, then we notify the SE that
 
5929
    it should become the actual table. Later, we will recycle the old table.
 
5930
    However, in case of ALTER TABLE RENAME there might be no intermediate
 
5931
    table. This is when the old and new tables are compatible, according to
 
5932
    compare_table(). Then, we need one additional call to
 
5933
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
 
5934
    actual rename in the SE and the FRM is not touched. Note that, if the
 
5935
    table is renamed and the SE is also changed, then an intermediate table
 
5936
    is created and the additional call will not take place.
 
5937
  */
 
5938
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
 
5939
                         FN_TO_IS_TMP))
 
5940
  {
 
5941
    error=1;
 
5942
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
5943
  }
 
5944
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
 
5945
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
 
5946
  {
 
5947
    /* Try to get everything back. */
 
5948
    error=1;
 
5949
    VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
 
5950
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
5951
    VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
 
5952
                            FN_FROM_IS_TMP));
 
5953
  }
 
5954
 
 
5955
  if (error)
 
5956
  {
 
5957
    /* This shouldn't happen. But let us play it safe. */
 
5958
    goto err_with_placeholders;
 
5959
  }
 
5960
 
 
5961
  VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
 
5962
 
 
5963
end_online:
 
5964
  if (thd->locked_tables && new_name == table_name && new_db == db)
 
5965
  {
 
5966
    thd->in_lock_tables= 1;
 
5967
    error= reopen_tables(thd, 1, 1);
 
5968
    thd->in_lock_tables= 0;
 
5969
    if (error)
 
5970
      goto err_with_placeholders;
 
5971
  }
 
5972
  VOID(pthread_mutex_unlock(&LOCK_open));
 
5973
 
 
5974
  thd_proc_info(thd, "end");
 
5975
 
 
5976
  ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
 
5977
                      thd->query, thd->query_length,
 
5978
                      db, table_name);
 
5979
 
 
5980
  assert(!(mysql_bin_log.is_open() &&
 
5981
                thd->current_stmt_binlog_row_based &&
 
5982
                (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
 
5983
  write_bin_log(thd, true, thd->query, thd->query_length);
 
5984
 
 
5985
  if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
 
5986
  {
 
5987
    /*
 
5988
      For the alter table to be properly flushed to the logs, we
 
5989
      have to open the new table.  If not, we get a problem on server
 
5990
      shutdown. But we do not need to attach MERGE children.
 
5991
    */
 
5992
    char path[FN_REFLEN];
 
5993
    TABLE *t_table;
 
5994
    build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
 
5995
    t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
 
5996
    if (t_table)
 
5997
    {
 
5998
      intern_close_table(t_table);
 
5999
      my_free(t_table, MYF(0));
 
6000
    }
 
6001
    else
 
6002
      sql_print_warning("Could not open table %s.%s after rename\n",
 
6003
                        new_db,table_name);
 
6004
    ha_flush_logs(old_db_type);
 
6005
  }
 
6006
  table_list->table=0;                          // For query cache
 
6007
 
 
6008
  if (thd->locked_tables && (new_name != table_name || new_db != db))
 
6009
  {
 
6010
    /*
 
6011
      If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
 
6012
      to remove placeholders for the old table and for the target table
 
6013
      from the list of open tables and table cache. If we are not under
 
6014
      LOCK TABLES we can rely on close_thread_tables() doing this job.
 
6015
    */
 
6016
    pthread_mutex_lock(&LOCK_open);
 
6017
    unlink_open_table(thd, table, false);
 
6018
    unlink_open_table(thd, name_lock, false);
 
6019
    pthread_mutex_unlock(&LOCK_open);
 
6020
  }
 
6021
 
 
6022
end_temporary:
 
6023
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
6024
           (ulong) (copied + deleted), (ulong) deleted,
 
6025
           (ulong) thd->cuted_fields);
 
6026
  my_ok(thd, copied + deleted, 0L, tmp_name);
 
6027
  thd->some_tables_deleted=0;
 
6028
  return(false);
 
6029
 
 
6030
err1:
 
6031
  if (new_table)
 
6032
  {
 
6033
    /* close_temporary_table() frees the new_table pointer. */
 
6034
    close_temporary_table(thd, new_table, 1, 1);
 
6035
  }
 
6036
  else
 
6037
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
 
6038
 
 
6039
err:
 
6040
  /*
 
6041
    No default value was provided for a DATE/DATETIME field, the
 
6042
    current sql_mode doesn't allow the '0000-00-00' value and
 
6043
    the table to be altered isn't empty.
 
6044
    Report error here.
 
6045
  */
 
6046
  if (alter_info->error_if_not_empty && thd->row_count)
 
6047
  {
 
6048
    const char *f_val= 0;
 
6049
    enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
 
6050
    switch (alter_info->datetime_field->sql_type)
 
6051
    {
 
6052
      case MYSQL_TYPE_NEWDATE:
 
6053
        f_val= "0000-00-00";
 
6054
        t_type= MYSQL_TIMESTAMP_DATE;
 
6055
        break;
 
6056
      case MYSQL_TYPE_DATETIME:
 
6057
        f_val= "0000-00-00 00:00:00";
 
6058
        t_type= MYSQL_TIMESTAMP_DATETIME;
 
6059
        break;
 
6060
      default:
 
6061
        /* Shouldn't get here. */
 
6062
        assert(0);
 
6063
    }
 
6064
    bool save_abort_on_warning= thd->abort_on_warning;
 
6065
    thd->abort_on_warning= true;
 
6066
    make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
 
6067
                                 f_val, strlength(f_val), t_type,
 
6068
                                 alter_info->datetime_field->field_name);
 
6069
    thd->abort_on_warning= save_abort_on_warning;
 
6070
  }
 
6071
  if (name_lock)
 
6072
  {
 
6073
    pthread_mutex_lock(&LOCK_open);
 
6074
    unlink_open_table(thd, name_lock, false);
 
6075
    pthread_mutex_unlock(&LOCK_open);
 
6076
  }
 
6077
  return(true);
 
6078
 
 
6079
err_with_placeholders:
 
6080
  /*
 
6081
    An error happened while we were holding exclusive name-lock on table
 
6082
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
6083
    from list of open tables list and table cache.
 
6084
  */
 
6085
  unlink_open_table(thd, table, false);
 
6086
  if (name_lock)
 
6087
    unlink_open_table(thd, name_lock, false);
 
6088
  VOID(pthread_mutex_unlock(&LOCK_open));
 
6089
  return(true);
 
6090
}
 
6091
/* mysql_alter_table */
 
6092
 
 
6093
static int
 
6094
copy_data_between_tables(TABLE *from,TABLE *to,
 
6095
                         List<Create_field> &create,
 
6096
                         bool ignore,
 
6097
                         uint order_num, ORDER *order,
 
6098
                         ha_rows *copied,
 
6099
                         ha_rows *deleted,
 
6100
                         enum enum_enable_or_disable keys_onoff,
 
6101
                         bool error_if_not_empty)
 
6102
{
 
6103
  int error;
 
6104
  Copy_field *copy,*copy_end;
 
6105
  ulong found_count,delete_count;
 
6106
  THD *thd= current_thd;
 
6107
  uint length= 0;
 
6108
  SORT_FIELD *sortorder;
 
6109
  READ_RECORD info;
 
6110
  TABLE_LIST   tables;
 
6111
  List<Item>   fields;
 
6112
  List<Item>   all_fields;
 
6113
  ha_rows examined_rows;
 
6114
  bool auto_increment_field_copied= 0;
 
6115
  ulong save_sql_mode;
 
6116
  uint64_t prev_insert_id;
 
6117
 
 
6118
  /*
 
6119
    Turn off recovery logging since rollback of an alter table is to
 
6120
    delete the new table so there is no need to log the changes to it.
 
6121
    
 
6122
    This needs to be done before external_lock
 
6123
  */
 
6124
  error= ha_enable_transaction(thd, false);
 
6125
  if (error)
 
6126
    return(-1);
 
6127
  
 
6128
  if (!(copy= new Copy_field[to->s->fields]))
 
6129
    return(-1);                         /* purecov: inspected */
 
6130
 
 
6131
  if (to->file->ha_external_lock(thd, F_WRLCK))
 
6132
    return(-1);
 
6133
 
 
6134
  /* We need external lock before we can disable/enable keys */
 
6135
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
6136
 
 
6137
  /* We can abort alter table for any table type */
 
6138
  thd->abort_on_warning= !ignore;
 
6139
 
 
6140
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
6141
  to->file->ha_start_bulk_insert(from->file->stats.records);
 
6142
 
 
6143
  save_sql_mode= thd->variables.sql_mode;
 
6144
 
 
6145
  List_iterator<Create_field> it(create);
 
6146
  Create_field *def;
 
6147
  copy_end=copy;
 
6148
  for (Field **ptr=to->field ; *ptr ; ptr++)
 
6149
  {
 
6150
    def=it++;
 
6151
    if (def->field)
 
6152
    {
 
6153
      if (*ptr == to->next_number_field)
 
6154
      {
 
6155
        auto_increment_field_copied= true;
 
6156
        /*
 
6157
          If we are going to copy contents of one auto_increment column to
 
6158
          another auto_increment column it is sensible to preserve zeroes.
 
6159
          This condition also covers case when we are don't actually alter
 
6160
          auto_increment column.
 
6161
        */
 
6162
        if (def->field == from->found_next_number_field)
 
6163
          thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
 
6164
      }
 
6165
      (copy_end++)->set(*ptr,def->field,0);
 
6166
    }
 
6167
 
 
6168
  }
 
6169
 
 
6170
  found_count=delete_count=0;
 
6171
 
 
6172
  if (order)
 
6173
  {
 
6174
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
 
6175
    {
 
6176
      char warn_buff[MYSQL_ERRMSG_SIZE];
 
6177
      snprintf(warn_buff, sizeof(warn_buff), 
 
6178
               "ORDER BY ignored as there is a user-defined clustered index"
 
6179
               " in the table '%-.192s'", from->s->table_name.str);
 
6180
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
6181
                   warn_buff);
 
6182
    }
 
6183
    else
 
6184
    {
 
6185
      from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
 
6186
                                                MYF(MY_FAE | MY_ZEROFILL));
 
6187
      bzero((char *) &tables, sizeof(tables));
 
6188
      tables.table= from;
 
6189
      tables.alias= tables.table_name= from->s->table_name.str;
 
6190
      tables.db= from->s->db.str;
 
6191
      error= 1;
 
6192
 
 
6193
      if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
 
6194
          setup_order(thd, thd->lex->select_lex.ref_pointer_array,
 
6195
                      &tables, fields, all_fields, order) ||
 
6196
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
6197
          (from->sort.found_records= filesort(thd, from, sortorder, length,
 
6198
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
 
6199
                                              1, &examined_rows)) ==
 
6200
          HA_POS_ERROR)
 
6201
        goto err;
 
6202
    }
 
6203
  };
 
6204
 
 
6205
  /* Tell handler that we have values for all columns in the to table */
 
6206
  to->use_all_columns();
 
6207
  init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
 
6208
  if (ignore)
 
6209
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
6210
  thd->row_count= 0;
 
6211
  restore_record(to, s->default_values);        // Create empty record
 
6212
  while (!(error=info.read_record(&info)))
 
6213
  {
 
6214
    if (thd->killed)
 
6215
    {
 
6216
      thd->send_kill_message();
 
6217
      error= 1;
 
6218
      break;
 
6219
    }
 
6220
    thd->row_count++;
 
6221
    /* Return error if source table isn't empty. */
 
6222
    if (error_if_not_empty)
 
6223
    {
 
6224
      error= 1;
 
6225
      break;
 
6226
    }
 
6227
    if (to->next_number_field)
 
6228
    {
 
6229
      if (auto_increment_field_copied)
 
6230
        to->auto_increment_field_not_null= true;
 
6231
      else
 
6232
        to->next_number_field->reset();
 
6233
    }
 
6234
    
 
6235
    for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
 
6236
    {
 
6237
      copy_ptr->do_copy(copy_ptr);
 
6238
    }
 
6239
    prev_insert_id= to->file->next_insert_id;
 
6240
    error=to->file->ha_write_row(to->record[0]);
 
6241
    to->auto_increment_field_not_null= false;
 
6242
    if (error)
 
6243
    {
 
6244
      if (!ignore ||
 
6245
          to->file->is_fatal_error(error, HA_CHECK_DUP))
 
6246
      {
 
6247
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
 
6248
         {
 
6249
           uint key_nr= to->file->get_dup_key(error);
 
6250
           if ((int) key_nr >= 0)
 
6251
           {
 
6252
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
 
6253
             if (key_nr == 0 &&
 
6254
                 (to->key_info[0].key_part[0].field->flags &
 
6255
                  AUTO_INCREMENT_FLAG))
 
6256
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
6257
             to->file->print_keydup_error(key_nr, err_msg);
 
6258
             break;
 
6259
           }
 
6260
         }
 
6261
 
 
6262
        to->file->print_error(error,MYF(0));
 
6263
        break;
 
6264
      }
 
6265
      to->file->restore_auto_increment(prev_insert_id);
 
6266
      delete_count++;
 
6267
    }
 
6268
    else
 
6269
      found_count++;
 
6270
  }
 
6271
  end_read_record(&info);
 
6272
  free_io_cache(from);
 
6273
  delete [] copy;                               // This is never 0
 
6274
 
 
6275
  if (to->file->ha_end_bulk_insert() && error <= 0)
 
6276
  {
 
6277
    to->file->print_error(my_errno,MYF(0));
 
6278
    error=1;
 
6279
  }
 
6280
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
6281
 
 
6282
  if (ha_enable_transaction(thd, true))
 
6283
  {
 
6284
    error= 1;
 
6285
    goto err;
 
6286
  }
 
6287
 
 
6288
  /*
 
6289
    Ensure that the new table is saved properly to disk so that we
 
6290
    can do a rename
 
6291
  */
 
6292
  if (ha_autocommit_or_rollback(thd, 0))
 
6293
    error=1;
 
6294
  if (end_active_trans(thd))
 
6295
    error=1;
 
6296
 
 
6297
 err:
 
6298
  thd->variables.sql_mode= save_sql_mode;
 
6299
  thd->abort_on_warning= 0;
 
6300
  free_io_cache(from);
 
6301
  *copied= found_count;
 
6302
  *deleted=delete_count;
 
6303
  to->file->ha_release_auto_increment();
 
6304
  if (to->file->ha_external_lock(thd,F_UNLCK))
 
6305
    error=1;
 
6306
  return(error > 0 ? -1 : 0);
 
6307
}
 
6308
 
 
6309
 
 
6310
/*
 
6311
  Recreates tables by calling mysql_alter_table().
 
6312
 
 
6313
  SYNOPSIS
 
6314
    mysql_recreate_table()
 
6315
    thd                 Thread handler
 
6316
    tables              Tables to recreate
 
6317
 
 
6318
 RETURN
 
6319
    Like mysql_alter_table().
 
6320
*/
 
6321
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
 
6322
{
 
6323
  HA_CREATE_INFO create_info;
 
6324
  Alter_info alter_info;
 
6325
 
 
6326
  assert(!table_list->next_global);
 
6327
  /*
 
6328
    table_list->table has been closed and freed. Do not reference
 
6329
    uninitialized data. open_tables() could fail.
 
6330
  */
 
6331
  table_list->table= NULL;
 
6332
 
 
6333
  bzero((char*) &create_info, sizeof(create_info));
 
6334
  create_info.row_type=ROW_TYPE_NOT_USED;
 
6335
  create_info.default_table_charset=default_charset_info;
 
6336
  /* Force alter table to recreate table */
 
6337
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
 
6338
  return(mysql_alter_table(thd, NullS, NullS, &create_info,
 
6339
                                table_list, &alter_info, 0,
 
6340
                                (ORDER *) 0, 0));
 
6341
}
 
6342
 
 
6343
 
 
6344
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
 
6345
                          HA_CHECK_OPT *check_opt)
 
6346
{
 
6347
  TABLE_LIST *table;
 
6348
  List<Item> field_list;
 
6349
  Item *item;
 
6350
  Protocol *protocol= thd->protocol;
 
6351
 
 
6352
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
 
6353
  item->maybe_null= 1;
 
6354
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
 
6355
                                          MY_INT64_NUM_DECIMAL_DIGITS));
 
6356
  item->maybe_null= 1;
 
6357
  if (protocol->send_fields(&field_list,
 
6358
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
6359
    return(true);
 
6360
 
 
6361
  /* Open one table after the other to keep lock time as short as possible. */
 
6362
  for (table= tables; table; table= table->next_local)
 
6363
  {
 
6364
    char table_name[NAME_LEN*2+2];
 
6365
    TABLE *t;
 
6366
 
 
6367
    strxmov(table_name, table->db ,".", table->table_name, NullS);
 
6368
 
 
6369
    t= table->table= open_n_lock_single_table(thd, table, TL_READ);
 
6370
    thd->clear_error();                 // these errors shouldn't get client
 
6371
 
 
6372
    protocol->prepare_for_resend();
 
6373
    protocol->store(table_name, system_charset_info);
 
6374
 
 
6375
    if (!t)
 
6376
    {
 
6377
      /* Table didn't exist */
 
6378
      protocol->store_null();
 
6379
      thd->clear_error();
 
6380
    }
 
6381
    else
 
6382
    {
 
6383
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
6384
          !(check_opt->flags & T_EXTEND))
 
6385
        protocol->store((uint64_t)t->file->checksum());
 
6386
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
6387
               (check_opt->flags & T_QUICK))
 
6388
        protocol->store_null();
 
6389
      else
 
6390
      {
 
6391
        /* calculating table's checksum */
 
6392
        ha_checksum crc= 0;
 
6393
        uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
6394
 
 
6395
        t->use_all_columns();
 
6396
 
 
6397
        if (t->file->ha_rnd_init(1))
 
6398
          protocol->store_null();
 
6399
        else
 
6400
        {
 
6401
          for (;;)
 
6402
          {
 
6403
            ha_checksum row_crc= 0;
 
6404
            int error= t->file->rnd_next(t->record[0]);
 
6405
            if (unlikely(error))
 
6406
            {
 
6407
              if (error == HA_ERR_RECORD_DELETED)
 
6408
                continue;
 
6409
              break;
 
6410
            }
 
6411
            if (t->s->null_bytes)
 
6412
            {
 
6413
              /* fix undefined null bits */
 
6414
              t->record[0][t->s->null_bytes-1] |= null_mask;
 
6415
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
 
6416
                t->record[0][0] |= 1;
 
6417
 
 
6418
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
 
6419
            }
 
6420
 
 
6421
            for (uint i= 0; i < t->s->fields; i++ )
 
6422
            {
 
6423
              Field *f= t->field[i];
 
6424
              if ((f->type() == MYSQL_TYPE_BLOB) ||
 
6425
                  (f->type() == MYSQL_TYPE_VARCHAR))
 
6426
              {
 
6427
                String tmp;
 
6428
                f->val_str(&tmp);
 
6429
                row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
 
6430
              }
 
6431
              else
 
6432
                row_crc= my_checksum(row_crc, f->ptr,
 
6433
                                     f->pack_length());
 
6434
            }
 
6435
 
 
6436
            crc+= row_crc;
 
6437
          }
 
6438
          protocol->store((uint64_t)crc);
 
6439
          t->file->ha_rnd_end();
 
6440
        }
 
6441
      }
 
6442
      thd->clear_error();
 
6443
      close_thread_tables(thd);
 
6444
      table->table=0;                           // For query cache
 
6445
    }
 
6446
    if (protocol->write())
 
6447
      goto err;
 
6448
  }
 
6449
 
 
6450
  my_eof(thd);
 
6451
  return(false);
 
6452
 
 
6453
 err:
 
6454
  close_thread_tables(thd);                     // Shouldn't be needed
 
6455
  if (table)
 
6456
    table->table=0;
 
6457
  return(true);
 
6458
}
 
6459
 
 
6460
static bool check_engine(THD *thd, const char *table_name,
 
6461
                         HA_CREATE_INFO *create_info)
 
6462
{
 
6463
  handlerton **new_engine= &create_info->db_type;
 
6464
  handlerton *req_engine= *new_engine;
 
6465
  bool no_substitution= 1;
 
6466
  if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
 
6467
                                  no_substitution, 1)))
2212
6468
    return true;
2213
 
  }
2214
 
 
2215
 
  return res;
2216
 
}
2217
 
 
2218
 
 
2219
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2220
 
{
2221
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2222
 
 
2223
 
  return(admin_table(session, tables, check_opt,
2224
 
                                "analyze", lock_type, true,
2225
 
                                &Cursor::ha_analyze));
2226
 
}
2227
 
 
2228
 
 
2229
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2230
 
{
2231
 
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2232
 
 
2233
 
  return(admin_table(session, tables, check_opt,
2234
 
                                "check", lock_type,
2235
 
                                false,
2236
 
                                &Cursor::ha_check));
2237
 
}
2238
 
 
2239
 
} /* namespace drizzled */
 
6469
 
 
6470
  if (req_engine && req_engine != *new_engine)
 
6471
  {
 
6472
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
 
6473
                       ER_WARN_USING_OTHER_HANDLER,
 
6474
                       ER(ER_WARN_USING_OTHER_HANDLER),
 
6475
                       ha_resolve_storage_engine_name(*new_engine),
 
6476
                       table_name);
 
6477
  }
 
6478
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
 
6479
      ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
 
6480
  {
 
6481
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
6482
    {
 
6483
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
6484
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
 
6485
      *new_engine= 0;
 
6486
      return true;
 
6487
    }
 
6488
    *new_engine= myisam_hton;
 
6489
  }
 
6490
  return false;
 
6491
}