~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

pandora-build v0.71. Added check for avahi.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
/* drop and alter of tables */
17
17
 
18
18
#include <drizzled/server_includes.h>
19
 
#include <storage/myisam/myisam.h>
20
 
#include <drizzled/sql_show.h>
21
 
#include <drizzled/drizzled_error_messages.h>
22
 
 
23
 
int creating_table= 0;        // How many mysql_create_table are running
24
 
 
25
 
const char *primary_key_name="PRIMARY";
 
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 <mysys/hash.h>
 
26
#include <drizzled/sql_lex.h>
 
27
#include <drizzled/session.h>
 
28
#include <drizzled/sql_base.h>
 
29
#include <drizzled/db.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/replication_services.h>
 
35
#include <drizzled/table_proto.h>
 
36
#include <drizzled/plugin/client.h>
 
37
 
 
38
#include "drizzled/statement/alter_table.h" /* for drizzled::create_like_schema_frm, which will die soon */
 
39
 
 
40
#include <algorithm>
 
41
 
 
42
using namespace std;
 
43
using namespace drizzled;
 
44
 
 
45
static const char hexchars[]= "0123456789abcdef";
 
46
bool is_primary_key(KEY *key_info)
 
47
{
 
48
  static const char * primary_key_name="PRIMARY";
 
49
  return (strcmp(key_info->name, primary_key_name)==0);
 
50
}
 
51
 
 
52
const char* is_primary_key_name(const char* key_name)
 
53
{
 
54
  static const char * primary_key_name="PRIMARY";
 
55
  if (strcmp(key_name, primary_key_name)==0)
 
56
    return key_name;
 
57
  else
 
58
    return NULL;
 
59
}
26
60
 
27
61
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
28
62
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
29
 
static int copy_data_between_tables(TABLE *from,TABLE *to,
30
 
                                    List<Create_field> &create, bool ignore,
31
 
                                    uint order_num, ORDER *order,
32
 
                                    ha_rows *copied,ha_rows *deleted,
33
 
                                    enum enum_enable_or_disable keys_onoff,
34
 
                                    bool error_if_not_empty);
35
 
 
36
 
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
37
 
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
38
 
static int
39
 
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
40
 
                           Alter_info *alter_info,
41
 
                           bool tmp_table,
42
 
                               uint *db_options,
43
 
                               handler *file, KEY **key_info_buffer,
44
 
                               uint *key_count, int select_field_count);
45
 
static bool
46
 
mysql_prepare_alter_table(THD *thd, TABLE *table,
47
 
                          HA_CREATE_INFO *create_info,
48
 
                          Alter_info *alter_info);
 
63
 
 
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
 
65
 
 
66
void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
 
67
{
 
68
  /*
 
69
    If the table character set was not given explicitly,
 
70
    let's fetch the database default character set and
 
71
    apply it to the table.
 
72
  */
 
73
  if (create_info->default_table_charset == NULL)
 
74
    create_info->default_table_charset= get_default_db_collation(db);
 
75
}
49
76
 
50
77
/*
51
 
  Translate a file name to a table name (WL #1324).
 
78
  Translate a cursor name to a table name (WL #1324).
52
79
 
53
80
  SYNOPSIS
54
81
    filename_to_tablename()
55
 
      from                      The file name in my_charset_filename.
56
 
      to                OUT     The table name in system_charset_info.
 
82
      from                      The cursor name
 
83
      to                OUT     The table name
57
84
      to_length                 The size of the table name buffer.
58
85
 
59
86
  RETURN
60
87
    Table name length.
61
88
*/
62
 
uint filename_to_tablename(const char *from, char *to, uint to_length)
 
89
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
63
90
{
64
 
  uint errors;
65
 
  uint res;
 
91
  uint32_t length= 0;
66
92
 
67
 
  if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
 
93
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
68
94
  {
69
95
    /* Temporary table name. */
70
 
    res= (stpncpy(to, from, to_length) - to);
 
96
    length= strlen(strncpy(to, from, to_length));
71
97
  }
72
98
  else
73
99
  {
74
 
    res= strconvert(&my_charset_filename, from,
75
 
                    system_charset_info,  to, to_length, &errors);
76
 
    if (errors) // Old 5.0 name
 
100
    for (; *from  && length < to_length; length++, from++)
77
101
    {
78
 
      res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX,  from, NullS) -
79
 
            to);
80
 
      sql_print_error("Invalid (old?) table or database name '%s'", from);
81
 
      /*
82
 
        TODO: add a stored procedure for fix table and database names,
83
 
        and mention its name in error log.
84
 
      */
85
 
    }
 
102
      if (*from != '@')
 
103
      {
 
104
        to[length]= *from;
 
105
        continue;
 
106
      }
 
107
      /* We've found an escaped char - skip the @ */
 
108
      from++;
 
109
      to[length]= 0;
 
110
      /* There will be a two-position hex-char version of the char */
 
111
      for (int x=1; x >= 0; x--)
 
112
      {
 
113
        if (*from >= '0' && *from <= '9')
 
114
          to[length] += ((*from++ - '0') << (4 * x));
 
115
        else if (*from >= 'a' && *from <= 'f')
 
116
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
117
      }
 
118
      /* Backup because we advanced extra in the inner loop */
 
119
      from--;
 
120
    } 
86
121
  }
87
122
 
88
 
  return(res);
 
123
  return length;
89
124
}
90
125
 
91
126
 
92
127
/*
93
 
  Translate a table name to a file name (WL #1324).
 
128
  Translate a table name to a cursor name (WL #1324).
94
129
 
95
130
  SYNOPSIS
96
131
    tablename_to_filename()
97
 
      from                      The table name in system_charset_info.
98
 
      to                OUT     The file name in my_charset_filename.
99
 
      to_length                 The size of the file name buffer.
 
132
      from                      The table name
 
133
      to                OUT     The cursor name
 
134
      to_length                 The size of the cursor name buffer.
100
135
 
101
136
  RETURN
102
 
    File name length.
 
137
    true if errors happen. false on success.
103
138
*/
104
 
 
105
 
uint tablename_to_filename(const char *from, char *to, uint to_length)
 
139
bool tablename_to_filename(const char *from, char *to, size_t to_length)
106
140
{
107
 
  uint errors, length;
108
 
 
109
 
  if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
110
 
                                 MYSQL50_TABLE_NAME_PREFIX_LENGTH))
111
 
    return((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
112
 
                                to_length-1) -
113
 
                        (from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
114
 
  length= strconvert(system_charset_info, from,
115
 
                     &my_charset_filename, to, to_length, &errors);
 
141
  
 
142
  size_t length= 0;
 
143
  for (; *from  && length < to_length; length++, from++)
 
144
  {
 
145
    if ((*from >= '0' && *from <= '9') ||
 
146
        (*from >= 'A' && *from <= 'Z') ||
 
147
        (*from >= 'a' && *from <= 'z') ||
 
148
/* OSX defines an extra set of high-bit and multi-byte characters
 
149
   that cannot be used on the filesystem. Instead of trying to sort
 
150
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
151
   It won't really hurt anything - it'll just make some filenames ugly. */
 
152
#if !defined(TARGET_OS_OSX)
 
153
        ((unsigned char)*from >= 128) ||
 
154
#endif
 
155
        (*from == '_') ||
 
156
        (*from == ' ') ||
 
157
        (*from == '-'))
 
158
    {
 
159
      to[length]= *from;
 
160
      continue;
 
161
    }
 
162
   
 
163
    if (length + 3 >= to_length)
 
164
      return true;
 
165
 
 
166
    /* We need to escape this char in a way that can be reversed */
 
167
    to[length++]= '@';
 
168
    to[length++]= hexchars[(*from >> 4) & 15];
 
169
    to[length]= hexchars[(*from) & 15];
 
170
  }
 
171
 
116
172
  if (check_if_legal_tablename(to) &&
117
173
      length + 4 < to_length)
118
174
  {
119
175
    memcpy(to + length, "@@@", 4);
120
176
    length+= 3;
121
177
  }
122
 
  return(length);
 
178
  return false;
123
179
}
124
180
 
125
181
 
126
182
/*
127
 
  Creates path to a file: mysql_data_dir/db/table.ext
 
183
  Creates path to a cursor: drizzle_data_dir/db/table.ext
128
184
 
129
185
  SYNOPSIS
130
186
   build_table_filename()
131
 
     buff                       Where to write result in my_charset_filename.
 
187
     buff                       Where to write result
132
188
                                This may be the same as table_name.
133
189
     bufflen                    buff size
134
 
     db                         Database name in system_charset_info.
135
 
     table_name                 Table name in system_charset_info.
 
190
     db                         Database name
 
191
     table_name                 Table name
136
192
     ext                        File extension.
137
193
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
138
194
                                table_name is temporary, do not change.
140
196
  NOTES
141
197
 
142
198
    Uses database and table name, and extension to create
143
 
    a file name in mysql_data_dir. Database and table
 
199
    a cursor name in drizzle_data_dir. Database and table
144
200
    names are converted from system_charset_info into "fscs".
145
201
    Unless flags indicate a temporary table name.
146
202
    'db' is always converted.
147
203
    'ext' is not converted.
148
204
 
149
 
    The conversion suppression is required for ALTER TABLE. This
 
205
    The conversion suppression is required for ALTER Table. This
150
206
    statement creates intermediate tables. These are regular
151
207
    (non-temporary) tables with a temporary name. Their path names must
152
208
    be derivable from the table name. So we cannot use
153
209
    build_tmptable_filename() for them.
154
210
 
155
211
  RETURN
156
 
    path length
 
212
    path length on success, 0 on failure
157
213
*/
158
214
 
159
 
uint build_table_filename(char *buff, size_t bufflen, const char *db,
160
 
                          const char *table_name, const char *ext, uint flags)
 
215
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
161
216
{
162
217
  char dbbuff[FN_REFLEN];
163
218
  char tbbuff[FN_REFLEN];
 
219
  bool conversion_error= false;
164
220
 
165
 
  if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
166
 
    stpncpy(tbbuff, table_name, sizeof(tbbuff));
 
221
  memset(tbbuff, 0, sizeof(tbbuff));
 
222
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
223
    strncpy(tbbuff, table_name, sizeof(tbbuff));
167
224
  else
168
 
    VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
169
 
 
170
 
  VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
171
 
 
172
 
  char *end = buff + bufflen;
173
 
  /* Don't add FN_ROOTDIR if mysql_data_home already includes it */
174
 
  char *pos = stpncpy(buff, mysql_data_home, bufflen);
 
225
  {
 
226
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
227
    if (conversion_error)
 
228
    {
 
229
      errmsg_printf(ERRMSG_LVL_ERROR,
 
230
                    _("Table name cannot be encoded and fit within filesystem "
 
231
                      "name length restrictions."));
 
232
      return 0;
 
233
    }
 
234
  }
 
235
  memset(dbbuff, 0, sizeof(dbbuff));
 
236
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
237
  if (conversion_error)
 
238
  {
 
239
    errmsg_printf(ERRMSG_LVL_ERROR,
 
240
                  _("Schema name cannot be encoded and fit within filesystem "
 
241
                    "name length restrictions."));
 
242
    return 0;
 
243
  }
 
244
   
 
245
 
175
246
  int rootdir_len= strlen(FN_ROOTDIR);
176
 
  if (pos - rootdir_len >= buff &&
177
 
      memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
178
 
    pos= stpncpy(pos, FN_ROOTDIR, end - pos);
179
 
  pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
180
 
#ifdef USE_SYMDIR
181
 
  unpack_dirname(buff, buff);
182
 
  pos= strend(buff);
183
 
#endif
184
 
  pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
185
 
 
186
 
  return(pos - buff);
 
247
  string table_path(drizzle_data_home);
 
248
  int without_rootdir= table_path.length()-rootdir_len;
 
249
 
 
250
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
251
  if (without_rootdir >= 0)
 
252
  {
 
253
    const char *tmp= table_path.c_str()+without_rootdir;
 
254
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
255
      table_path.append(FN_ROOTDIR);
 
256
  }
 
257
 
 
258
  table_path.append(dbbuff);
 
259
  table_path.append(FN_ROOTDIR);
 
260
  table_path.append(tbbuff);
 
261
 
 
262
  if (bufflen < table_path.length())
 
263
    return 0;
 
264
 
 
265
  strcpy(buff, table_path.c_str());
 
266
 
 
267
  return table_path.length();
187
268
}
188
269
 
189
270
 
190
271
/*
191
 
  Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
 
272
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
192
273
 
193
274
  SYNOPSIS
194
275
   build_tmptable_filename()
195
 
     thd                        The thread handle.
196
 
     buff                       Where to write result in my_charset_filename.
 
276
     session                    The thread handle.
 
277
     buff                       Where to write result
197
278
     bufflen                    buff size
198
279
 
199
280
  NOTES
200
281
 
201
282
    Uses current_pid, thread_id, and tmp_table counter to create
202
 
    a file name in mysql_tmpdir.
 
283
    a cursor name in drizzle_tmpdir.
203
284
 
204
285
  RETURN
205
 
    path length
 
286
    path length on success, 0 on failure
206
287
*/
207
288
 
208
 
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
 
289
static uint32_t build_tmptable_filename(Session* session,
 
290
                                        char *buff, size_t bufflen)
209
291
{
210
 
 
211
 
  char *p= stpncpy(buff, mysql_tmpdir, bufflen);
212
 
  snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
213
 
              tmp_file_prefix, current_pid,
214
 
              thd->thread_id, thd->tmp_table++, reg_ext);
215
 
 
216
 
  if (lower_case_table_names)
217
 
  {
218
 
    /* Convert all except tmpdir to lower case */
219
 
    my_casedn_str(files_charset_info, p);
220
 
  }
221
 
 
222
 
  uint length= unpack_filename(buff, buff);
223
 
  return(length);
 
292
  uint32_t length;
 
293
  ostringstream path_str, post_tmpdir_str;
 
294
  string tmp;
 
295
 
 
296
  path_str << drizzle_tmpdir;
 
297
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
298
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
299
  tmp= post_tmpdir_str.str();
 
300
 
 
301
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
302
 
 
303
  path_str << tmp;
 
304
 
 
305
  if (bufflen < path_str.str().length())
 
306
    length= 0;
 
307
  else
 
308
    length= unpack_filename(buff, path_str.str().c_str());
 
309
 
 
310
  return length;
224
311
}
225
312
 
226
313
/*
227
314
  SYNOPSIS
228
315
    write_bin_log()
229
 
    thd                           Thread object
230
 
    clear_error                   is clear_error to be called
 
316
    session                           Thread object
231
317
    query                         Query to log
232
318
    query_length                  Length of query
233
319
 
236
322
 
237
323
  DESCRIPTION
238
324
    Write the binlog if open, routine used in multiple places in this
239
 
    file
 
325
    cursor
240
326
*/
241
327
 
242
 
void write_bin_log(THD *thd, bool clear_error,
243
 
                   char const *query, ulong query_length)
244
 
{
245
 
  if (mysql_bin_log.is_open())
 
328
void write_bin_log(Session *session,
 
329
                   char const *query, size_t query_length)
 
330
{
 
331
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
332
  replication_services.rawStatement(session, query, query_length);
 
333
}
 
334
 
 
335
 
 
336
/* Should should be refactored to go away */
 
337
static void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
 
338
{
 
339
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
340
  string built_query;
 
341
 
 
342
  if (if_exists)
 
343
    built_query.append("DROP TABLE IF EXISTS ");
 
344
  else
 
345
    built_query.append("DROP TABLE ");
 
346
 
 
347
  built_query.append("`");
 
348
  if (session->db == NULL || strcmp(db_name ,session->db) != 0)
246
349
  {
247
 
    if (clear_error)
248
 
      thd->clear_error();
249
 
    thd->binlog_query(THD::STMT_QUERY_TYPE,
250
 
                      query, query_length, false, false);
 
350
    built_query.append(db_name);
 
351
    built_query.append("`.`");
251
352
  }
 
353
 
 
354
  built_query.append(table_name);
 
355
  built_query.append("`");
 
356
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
252
357
}
253
358
 
254
359
 
257
362
 
258
363
  SYNOPSIS
259
364
   mysql_rm_table()
260
 
   thd                  Thread handle
 
365
   session                      Thread handle
261
366
   tables               List of tables to delete
262
367
   if_exists            If 1, don't give error if one table doesn't exists
263
368
 
276
381
 
277
382
*/
278
383
 
279
 
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, bool drop_temporary)
 
384
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
280
385
{
281
386
  bool error, need_start_waiting= false;
282
387
 
283
388
  if (tables && tables->schema_table)
284
389
  {
285
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
390
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
286
391
    return(true);
287
392
  }
288
393
 
290
395
 
291
396
  if (!drop_temporary)
292
397
  {
293
 
    if (!thd->locked_tables &&
294
 
        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
 
398
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
295
399
      return(true);
296
400
  }
297
401
 
300
404
    LOCK_open during wait_if_global_read_lock(), other threads could not
301
405
    close their tables. This would make a pretty deadlock.
302
406
  */
303
 
  error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
 
407
  error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, false);
304
408
 
305
409
  if (need_start_waiting)
306
 
    start_waiting_global_read_lock(thd);
 
410
    start_waiting_global_read_lock(session);
307
411
 
308
412
  if (error)
309
413
    return(true);
310
 
  my_ok(thd);
 
414
  session->my_ok();
311
415
  return(false);
312
416
}
313
417
 
316
420
 
317
421
  SYNOPSIS
318
422
    mysql_rm_table_part2()
319
 
    thd                 Thread handler
 
423
    session                     Thread Cursor
320
424
    tables              Tables to drop
321
425
    if_exists           If set, don't give an error if table doesn't exists.
322
426
                        In this case we give an warning of level 'NOTE'
323
427
    drop_temporary      Only drop temporary tables
324
 
    drop_view           Allow to delete VIEW .frm
325
428
    dont_log_query      Don't write query to log files. This will also not
326
 
                        generate warnings if the handler files doesn't exists  
 
429
                        generate warnings if the Cursor files doesn't exists
327
430
 
328
431
  TODO:
329
432
    When logging to the binary log, we should log
341
444
   -1   Thread was killed
342
445
*/
343
446
 
344
 
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
345
 
                         bool drop_temporary, bool drop_view,
346
 
                         bool dont_log_query)
 
447
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
448
                         bool drop_temporary, bool dont_log_query)
347
449
{
348
 
  TABLE_LIST *table;
349
 
  char path[FN_REFLEN], *alias;
350
 
  uint path_length;
 
450
  TableList *table;
 
451
  char path[FN_REFLEN];
 
452
  uint32_t path_length= 0;
351
453
  String wrong_tables;
352
454
  int error= 0;
353
 
  int non_temp_tables_count= 0;
354
 
  bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
355
 
  String built_query;
356
 
 
357
 
  if (thd->current_stmt_binlog_row_based && !dont_log_query)
358
 
  {
359
 
    built_query.set_charset(system_charset_info);
360
 
    if (if_exists)
361
 
      built_query.append("DROP TABLE IF EXISTS ");
362
 
    else
363
 
      built_query.append("DROP TABLE ");
364
 
  }
365
 
 
366
 
  mysql_ha_rm_tables(thd, tables, false);
367
 
 
368
 
  pthread_mutex_lock(&LOCK_open);
 
455
  bool foreign_key_error= false;
 
456
 
 
457
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
369
458
 
370
459
  /*
371
460
    If we have the table in the definition cache, we don't have to check the
372
 
    .frm file to find if the table is a normal table (not view) and what
 
461
    .frm cursor to find if the table is a normal table (not view) and what
373
462
    engine to use.
374
463
  */
375
464
 
376
465
  for (table= tables; table; table= table->next_local)
377
466
  {
378
 
    TABLE_SHARE *share;
 
467
    TableShare *share;
379
468
    table->db_type= NULL;
380
 
    if ((share= get_cached_table_share(table->db, table->table_name)))
 
469
    if ((share= TableShare::getShare(table->db, table->table_name)))
381
470
      table->db_type= share->db_type();
382
471
  }
383
472
 
384
 
  if (!drop_temporary && lock_table_names_exclusively(thd, tables))
 
473
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
385
474
  {
386
475
    pthread_mutex_unlock(&LOCK_open);
387
 
    return(1);
 
476
    return 1;
388
477
  }
389
478
 
390
479
  /* Don't give warnings for not found errors, as we already generate notes */
391
 
  thd->no_warnings_for_error= 1;
 
480
  session->no_warnings_for_error= 1;
392
481
 
393
482
  for (table= tables; table; table= table->next_local)
394
483
  {
395
484
    char *db=table->db;
396
 
    handlerton *table_type;
397
 
    enum legacy_db_type frm_db_type;
398
 
 
399
 
 
400
 
    error= drop_temporary_table(thd, table);
 
485
    plugin::StorageEngine *table_type;
 
486
 
 
487
    error= session->drop_temporary_table(table);
401
488
 
402
489
    switch (error) {
403
490
    case  0:
404
491
      // removed temporary table
405
 
      tmp_table_deleted= 1;
406
492
      continue;
407
493
    case -1:
408
 
      assert(thd->in_sub_stmt);
409
494
      error= 1;
410
495
      goto err_with_placeholders;
411
496
    default:
413
498
      error= 0;
414
499
    }
415
500
 
416
 
    /*
417
 
      If row-based replication is used and the table is not a
418
 
      temporary table, we add the table name to the drop statement
419
 
      being built.  The string always end in a comma and the comma
420
 
      will be chopped off before being written to the binary log.
421
 
      */
422
 
    if (thd->current_stmt_binlog_row_based && !dont_log_query)
423
 
    {
424
 
      non_temp_tables_count++;
425
 
      /*
426
 
        Don't write the database name if it is the current one (or if
427
 
        thd->db is NULL).
428
 
      */
429
 
      built_query.append("`");
430
 
      if (thd->db == NULL || strcmp(db,thd->db) != 0)
431
 
      {
432
 
        built_query.append(db);
433
 
        built_query.append("`.`");
434
 
      }
435
 
 
436
 
      built_query.append(table->table_name);
437
 
      built_query.append("`,");
438
 
    }
439
 
 
440
501
    table_type= table->db_type;
441
502
    if (!drop_temporary)
442
503
    {
443
 
      TABLE *locked_table;
444
 
      abort_locked_tables(thd, db, table->table_name);
445
 
      remove_table_from_cache(thd, db, table->table_name,
 
504
      Table *locked_table;
 
505
      abort_locked_tables(session, db, table->table_name);
 
506
      remove_table_from_cache(session, db, table->table_name,
446
507
                              RTFC_WAIT_OTHER_THREAD_FLAG |
447
508
                              RTFC_CHECK_KILLED_FLAG);
448
509
      /*
449
510
        If the table was used in lock tables, remember it so that
450
511
        unlock_table_names can free it
451
512
      */
452
 
      if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
 
513
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
453
514
        table->table= locked_table;
454
515
 
455
 
      if (thd->killed)
 
516
      if (session->killed)
456
517
      {
457
518
        error= -1;
458
519
        goto err_with_placeholders;
459
520
      }
460
 
      alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
461
 
      /* remove .frm file and engine files */
462
 
      path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
463
 
                                        table->internal_tmp_table ?
464
 
                                        FN_IS_TMP : 0);
 
521
      /* remove .frm cursor and engine files */
 
522
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
465
523
    }
 
524
 
466
525
    if (drop_temporary ||
467
 
        ((table_type == NULL && (access(path, F_OK) && ha_create_table_from_engine(thd, db, alias))) ||
468
 
         (!drop_view && mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
 
526
        ((table_type == NULL
 
527
          && (plugin::StorageEngine::getTableDefinition(*session, 
 
528
                                                        path, 
 
529
                                                        db, 
 
530
                                                        table->table_name, 
 
531
                                                        table->internal_tmp_table) != EEXIST))))
469
532
    {
470
533
      // Table was not found on disk and table can't be created from engine
471
534
      if (if_exists)
472
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
535
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
473
536
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
474
537
                            table->table_name);
475
538
      else
477
540
    }
478
541
    else
479
542
    {
480
 
      char *end;
481
 
      if (table_type == NULL)
482
 
      {
483
 
        mysql_frm_type(thd, path, &frm_db_type);
484
 
        table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
485
 
      }
486
 
      // Remove extension for delete
487
 
      *(end= path + path_length - reg_ext_length)= '\0';
488
 
      error= ha_delete_table(thd, table_type, path, db, table->table_name,
489
 
                             !dont_log_query);
490
 
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && 
491
 
          (if_exists || table_type == NULL))
 
543
      error= plugin::StorageEngine::dropTable(*session, path, db,
 
544
                                                table->table_name,
 
545
                                                ! dont_log_query);
 
546
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
492
547
      {
493
548
        error= 0;
494
 
        thd->clear_error();
 
549
        session->clear_error();
495
550
      }
 
551
 
496
552
      if (error == HA_ERR_ROW_IS_REFERENCED)
497
553
      {
498
554
        /* the table is referenced by a foreign key constraint */
499
 
        foreign_key_error=1;
500
 
      }
501
 
      if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
502
 
      {
503
 
        int new_error;
504
 
        /* Delete the table definition file */
505
 
        stpcpy(end,reg_ext);
506
 
        if (!(new_error=my_delete(path,MYF(MY_WME))))
507
 
        {
508
 
          some_tables_deleted=1;
509
 
          new_error= 0;
510
 
        }
511
 
        error|= new_error;
 
555
        foreign_key_error= true;
512
556
      }
513
557
    }
 
558
 
 
559
    if (error == 0 || (if_exists && foreign_key_error == false))
 
560
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
561
 
514
562
    if (error)
515
563
    {
516
564
      if (wrong_tables.length())
523
571
    on the table name.
524
572
  */
525
573
  pthread_mutex_unlock(&LOCK_open);
526
 
  thd->thread_specific_used|= tmp_table_deleted;
527
574
  error= 0;
528
575
  if (wrong_tables.length())
529
576
  {
537
584
    error= 1;
538
585
  }
539
586
 
540
 
  if (some_tables_deleted || tmp_table_deleted || !error)
541
 
  {
542
 
    if (!dont_log_query)
543
 
    {
544
 
      if (!thd->current_stmt_binlog_row_based ||
545
 
          (non_temp_tables_count > 0 && !tmp_table_deleted))
546
 
      {
547
 
        /*
548
 
          In this case, we are either using statement-based
549
 
          replication or using row-based replication but have only
550
 
          deleted one or more non-temporary tables (and no temporary
551
 
          tables).  In this case, we can write the original query into
552
 
          the binary log.
553
 
         */
554
 
        write_bin_log(thd, !error, thd->query, thd->query_length);
555
 
      }
556
 
      else if (thd->current_stmt_binlog_row_based &&
557
 
               non_temp_tables_count > 0 &&
558
 
               tmp_table_deleted)
559
 
      {
560
 
        /*
561
 
          In this case we have deleted both temporary and
562
 
          non-temporary tables, so:
563
 
          - since we have deleted a non-temporary table we have to
564
 
            binlog the statement, but
565
 
          - since we have deleted a temporary table we cannot binlog
566
 
            the statement (since the table has not been created on the
567
 
            slave, this might cause the slave to stop).
568
 
 
569
 
          Instead, we write a built statement, only containing the
570
 
          non-temporary tables, to the binary log
571
 
        */
572
 
        built_query.chop();                  // Chop of the last comma
573
 
        built_query.append(" /* generated by server */");
574
 
        write_bin_log(thd, !error, built_query.ptr(), built_query.length());
575
 
      }
576
 
      /*
577
 
        The remaining cases are:
578
 
        - no tables where deleted and
579
 
        - only temporary tables where deleted and row-based
580
 
          replication is used.
581
 
        In both these cases, nothing should be written to the binary
582
 
        log.
583
 
      */
584
 
    }
585
 
  }
586
 
  pthread_mutex_lock(&LOCK_open);
 
587
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
587
588
err_with_placeholders:
588
 
  unlock_table_names(thd, tables, (TABLE_LIST*) 0);
 
589
  unlock_table_names(tables, NULL);
589
590
  pthread_mutex_unlock(&LOCK_open);
590
 
  thd->no_warnings_for_error= 0;
 
591
  session->no_warnings_for_error= 0;
 
592
 
591
593
  return(error);
592
594
}
593
595
 
597
599
 
598
600
  SYNOPSIS
599
601
    quick_rm_table()
600
 
      base                      The handlerton handle.
 
602
      base                      The plugin::StorageEngine handle.
601
603
      db                        The database name.
602
604
      table_name                The table name.
603
 
      flags                     flags for build_table_filename().
 
605
      is_tmp                    If the table is temp.
604
606
 
605
607
  RETURN
606
608
    0           OK
607
609
    != 0        Error
608
610
*/
609
611
 
610
 
bool quick_rm_table(handlerton *base,const char *db,
611
 
                    const char *table_name, uint flags)
 
612
bool quick_rm_table(Session& session, const char *db,
 
613
                    const char *table_name, bool is_tmp)
612
614
{
613
615
  char path[FN_REFLEN];
614
616
  bool error= 0;
615
617
 
616
 
  uint path_length= build_table_filename(path, sizeof(path),
617
 
                                         db, table_name, reg_ext, flags);
618
 
  if (my_delete(path,MYF(0)))
619
 
    error= 1; /* purecov: inspected */
620
 
  path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
621
 
  return(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
622
 
              error);
 
618
  build_table_filename(path, sizeof(path), db, table_name, is_tmp);
 
619
 
 
620
  return (plugin::StorageEngine::dropTable(session, path, db,
 
621
                                           table_name, 0)
 
622
          || error);
623
623
}
624
624
 
625
625
/*
638
638
static int sort_keys(KEY *a, KEY *b)
639
639
{
640
640
  ulong a_flags= a->flags, b_flags= b->flags;
641
 
  
 
641
 
642
642
  if (a_flags & HA_NOSAME)
643
643
  {
644
644
    if (!(b_flags & HA_NOSAME))
648
648
      /* Sort NOT NULL keys before other keys */
649
649
      return (a_flags & (HA_NULL_PART_KEY)) ? 1 : -1;
650
650
    }
651
 
    if (a->name == primary_key_name)
 
651
    if (is_primary_key(a))
652
652
      return -1;
653
 
    if (b->name == primary_key_name)
 
653
    if (is_primary_key(b))
654
654
      return 1;
655
655
    /* Sort keys don't containing partial segments before others */
656
656
    if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
687
687
    1             Error
688
688
*/
689
689
 
690
 
bool check_duplicates_in_interval(const char *set_or_name,
691
 
                                  const char *name, TYPELIB *typelib,
692
 
                                  const CHARSET_INFO * const cs, unsigned int *dup_val_count)
 
690
static bool check_duplicates_in_interval(const char *set_or_name,
 
691
                                         const char *name, TYPELIB *typelib,
 
692
                                         const CHARSET_INFO * const cs,
 
693
                                         unsigned int *dup_val_count)
693
694
{
694
695
  TYPELIB tmp= *typelib;
695
696
  const char **cur_value= typelib->type_names;
696
697
  unsigned int *cur_length= typelib->type_lengths;
697
 
  *dup_val_count= 0;  
698
 
  
 
698
  *dup_val_count= 0;
 
699
 
699
700
  for ( ; tmp.count > 1; cur_value++, cur_length++)
700
701
  {
701
702
    tmp.type_names++;
730
731
  RETURN VALUES
731
732
    void
732
733
*/
733
 
void calculate_interval_lengths(const CHARSET_INFO * const cs, TYPELIB *interval,
734
 
                                uint32_t *max_length, uint32_t *tot_length)
 
734
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
 
735
                                       TYPELIB *interval,
 
736
                                       uint32_t *max_length,
 
737
                                       uint32_t *tot_length)
735
738
{
736
739
  const char **pos;
737
 
  uint *len;
 
740
  uint32_t *len;
738
741
  *max_length= *tot_length= 0;
739
742
  for (pos= interval->type_names, len= interval->type_lengths;
740
743
       *pos ; pos++, len++)
741
744
  {
742
 
    uint length= cs->cset->numchars(cs, *pos, *pos + *len);
 
745
    uint32_t length= cs->cset->numchars(cs, *pos, *pos + *len);
743
746
    *tot_length+= length;
744
747
    set_if_bigger(*max_length, (uint32_t)length);
745
748
  }
746
749
}
747
750
 
748
 
 
749
751
/*
750
752
  Prepare a create_table instance for packing
751
753
 
757
759
    table_flags   table flags
758
760
 
759
761
  DESCRIPTION
760
 
    This function prepares a Create_field instance.
 
762
    This function prepares a CreateField instance.
761
763
    Fields such as pack_flag are valid after this call.
762
764
 
763
765
  RETURN VALUES
764
766
   0    ok
765
767
   1    Error
766
768
*/
767
 
 
768
 
int prepare_create_field(Create_field *sql_field, 
769
 
                         uint *blob_columns,
 
769
int prepare_create_field(CreateField *sql_field,
 
770
                         uint32_t *blob_columns,
770
771
                         int *timestamps, int *timestamps_with_niladic,
771
 
                         int64_t table_flags __attribute__((unused)))
 
772
                         int64_t )
772
773
{
773
774
  unsigned int dup_val_count;
774
775
 
780
781
 
781
782
  switch (sql_field->sql_type) {
782
783
  case DRIZZLE_TYPE_BLOB:
783
 
    sql_field->pack_flag=FIELDFLAG_BLOB |
784
 
      pack_length_to_packflag(sql_field->pack_length -
785
 
                              portable_sizeof_char_ptr);
786
 
    if (sql_field->charset->state & MY_CS_BINSORT)
787
 
      sql_field->pack_flag|=FIELDFLAG_BINARY;
788
 
    sql_field->length=8;                        // Unireg field length
789
 
    sql_field->unireg_check=Field::BLOB_FIELD;
 
784
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
 
785
    sql_field->length= 8; // Unireg field length
790
786
    (*blob_columns)++;
791
787
    break;
792
788
  case DRIZZLE_TYPE_VARCHAR:
793
789
    sql_field->pack_flag=0;
794
 
    if (sql_field->charset->state & MY_CS_BINSORT)
795
 
      sql_field->pack_flag|=FIELDFLAG_BINARY;
796
790
    break;
797
791
  case DRIZZLE_TYPE_ENUM:
798
 
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
799
 
      FIELDFLAG_INTERVAL;
800
 
    if (sql_field->charset->state & MY_CS_BINSORT)
801
 
      sql_field->pack_flag|=FIELDFLAG_BINARY;
802
 
    sql_field->unireg_check=Field::INTERVAL_FIELD;
803
 
    if (check_duplicates_in_interval("ENUM",sql_field->field_name,
804
 
                                 sql_field->interval,
805
 
                                     sql_field->charset, &dup_val_count))
806
 
      return(1);
 
792
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
 
793
    if (check_duplicates_in_interval("ENUM",
 
794
                                     sql_field->field_name,
 
795
                                     sql_field->interval,
 
796
                                     sql_field->charset,
 
797
                                     &dup_val_count))
 
798
      return 1;
807
799
    break;
808
 
  case DRIZZLE_TYPE_NEWDATE:  // Rest of string types
809
 
  case DRIZZLE_TYPE_TIME:
 
800
  case DRIZZLE_TYPE_DATE:  // Rest of string types
810
801
  case DRIZZLE_TYPE_DATETIME:
811
802
  case DRIZZLE_TYPE_NULL:
812
 
    sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
 
803
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
813
804
    break;
814
 
  case DRIZZLE_TYPE_NEWDECIMAL:
815
 
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
816
 
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
817
 
                           FIELDFLAG_DECIMAL) |
818
 
                          (sql_field->flags & DECIMAL_FLAG ?  FIELDFLAG_DECIMAL_POSITION : 0) |
819
 
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
 
805
  case DRIZZLE_TYPE_DECIMAL:
 
806
    sql_field->pack_flag= 0;
820
807
    break;
821
808
  case DRIZZLE_TYPE_TIMESTAMP:
822
809
    /* We should replace old TIMESTAMP fields with their newer analogs */
836
823
    (*timestamps)++;
837
824
    /* fall-through */
838
825
  default:
839
 
    sql_field->pack_flag=(FIELDFLAG_NUMBER |
840
 
                          (sql_field->flags & UNSIGNED_FLAG ? 0 :
841
 
                           FIELDFLAG_DECIMAL) |
842
 
                          f_settype((uint) sql_field->sql_type) |
843
 
                          (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
 
826
    sql_field->pack_flag=(0 |
 
827
                          f_settype((uint32_t) sql_field->sql_type));
844
828
    break;
845
829
  }
846
 
  if (!(sql_field->flags & NOT_NULL_FLAG))
847
 
    sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
848
 
  if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
849
 
    sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
850
 
  return(0);
 
830
  return 0;
851
831
}
852
832
 
853
 
/*
854
 
  Preparation for table creation
855
 
 
856
 
  SYNOPSIS
857
 
    mysql_prepare_create_table()
858
 
      thd                       Thread object.
859
 
      create_info               Create information (like MAX_ROWS).
860
 
      alter_info                List of columns and indexes to create
861
 
      tmp_table                 If a temporary table is to be created.
862
 
      db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
863
 
      file                      The handler for the new table.
864
 
      key_info_buffer     OUT   An array of KEY structs for the indexes.
865
 
      key_count           OUT   The number of elements in the array.
866
 
      select_field_count        The number of fields coming from a select table.
867
 
 
868
 
  DESCRIPTION
869
 
    Prepares the table and key structures for table creation.
870
 
 
871
 
  NOTES
872
 
    sets create_info->varchar if the table has a varchar
873
 
 
874
 
  RETURN VALUES
875
 
    false    OK
876
 
    true     error
877
 
*/
878
 
 
879
 
static int
880
 
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
881
 
                           Alter_info *alter_info,
882
 
                           bool tmp_table,
883
 
                               uint *db_options,
884
 
                               handler *file, KEY **key_info_buffer,
885
 
                               uint *key_count, int select_field_count)
 
833
int mysql_prepare_create_table(Session *session,
 
834
                               HA_CREATE_INFO *create_info,
 
835
                               message::Table *create_proto,
 
836
                               AlterInfo *alter_info,
 
837
                               bool tmp_table,
 
838
                               uint32_t *db_options,
 
839
                               Cursor *cursor,
 
840
                               KEY **key_info_buffer,
 
841
                               uint32_t *key_count,
 
842
                               int select_field_count)
886
843
{
887
844
  const char    *key_name;
888
 
  Create_field  *sql_field,*dup_field;
 
845
  CreateField   *sql_field,*dup_field;
889
846
  uint          field,null_fields,blob_columns,max_key_length;
890
847
  ulong         record_offset= 0;
891
848
  KEY           *key_info;
893
850
  int           timestamps= 0, timestamps_with_niladic= 0;
894
851
  int           field_no,dup_no;
895
852
  int           select_field_pos,auto_increment=0;
896
 
  List_iterator<Create_field> it(alter_info->create_list);
897
 
  List_iterator<Create_field> it2(alter_info->create_list);
898
 
  uint total_uneven_bit_length= 0;
 
853
  List_iterator<CreateField> it(alter_info->create_list);
 
854
  List_iterator<CreateField> it2(alter_info->create_list);
 
855
  uint32_t total_uneven_bit_length= 0;
899
856
 
900
857
  select_field_pos= alter_info->create_list.elements - select_field_count;
901
858
  null_fields=blob_columns=0;
902
 
  create_info->varchar= 0;
903
 
  max_key_length= file->max_key_length();
 
859
  max_key_length= cursor->max_key_length();
904
860
 
905
861
  for (field_no=0; (sql_field=it++) ; field_no++)
906
862
  {
915
871
    if (!sql_field->charset)
916
872
      sql_field->charset= create_info->default_table_charset;
917
873
    /*
918
 
      table_charset is set in ALTER TABLE if we want change character set
 
874
      table_charset is set in ALTER Table if we want change character set
919
875
      for all varchar/char columns.
920
876
      But the table charset must not affect the BLOB fields, so don't
921
877
      allow to change my_charset_bin to somethig else.
925
881
 
926
882
    save_cs= sql_field->charset;
927
883
    if ((sql_field->flags & BINCMP_FLAG) &&
928
 
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
929
 
                                                    MY_CS_BINSORT,MYF(0))))
 
884
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, MY_CS_BINSORT)))
930
885
    {
931
886
      char tmp[64];
932
 
      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
933
 
              STRING_WITH_LEN("_bin"));
 
887
      char *tmp_pos= tmp;
 
888
      strncpy(tmp_pos, save_cs->csname, sizeof(tmp)-4);
 
889
      tmp_pos+= strlen(tmp);
 
890
      strncpy(tmp_pos, STRING_WITH_LEN("_bin"));
934
891
      my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
935
892
      return(true);
936
893
    }
939
896
      Convert the default value from client character
940
897
      set into the column character set if necessary.
941
898
    */
942
 
    if (sql_field->def && 
 
899
    if (sql_field->def &&
943
900
        save_cs != sql_field->def->collation.collation &&
944
901
        (sql_field->sql_type == DRIZZLE_TYPE_ENUM))
945
902
    {
946
903
      /*
947
 
        Starting from 5.1 we work here with a copy of Create_field
 
904
        Starting from 5.1 we work here with a copy of CreateField
948
905
        created by the caller, not with the instance that was
949
906
        originally created during parsing. It's OK to create
950
907
        a temporary item and initialize with it a member of the
981
938
          occupied memory at the same time when we free this
982
939
          sql_field -- at the end of execution.
983
940
        */
984
 
        interval= sql_field->interval= typelib(thd->mem_root,
 
941
        interval= sql_field->interval= typelib(session->mem_root,
985
942
                                               sql_field->interval_list);
 
943
 
986
944
        List_iterator<String> int_it(sql_field->interval_list);
987
945
        String conv, *tmp;
988
946
        char comma_buf[4];
989
 
        int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
990
 
                                          (uchar*) comma_buf + 
 
947
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
 
948
                                          (unsigned char*) comma_buf +
991
949
                                          sizeof(comma_buf));
992
950
        assert(comma_length > 0);
993
 
        for (uint i= 0; (tmp= int_it++); i++)
 
951
 
 
952
        for (uint32_t i= 0; (tmp= int_it++); i++)
994
953
        {
995
 
          uint lengthsp;
 
954
          uint32_t lengthsp;
996
955
          if (String::needs_conversion(tmp->length(), tmp->charset(),
997
956
                                       cs, &dummy))
998
957
          {
999
 
            uint cnv_errs;
 
958
            uint32_t cnv_errs;
1000
959
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
1001
 
            interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
 
960
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
1002
961
                                                  conv.length());
1003
962
            interval->type_lengths[i]= conv.length();
1004
963
          }
1007
966
          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
1008
967
                                       interval->type_lengths[i]);
1009
968
          interval->type_lengths[i]= lengthsp;
1010
 
          ((uchar *)interval->type_names[i])[lengthsp]= '\0';
 
969
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
1011
970
        }
1012
971
        sql_field->interval_list.empty(); // Don't need interval_list anymore
1013
972
      }
1028
987
            }
1029
988
 
1030
989
            /* else, the defaults yield the correct length for NULLs. */
1031
 
          } 
 
990
          }
1032
991
          else /* not NULL */
1033
992
          {
1034
993
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
1042
1001
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
1043
1002
        sql_field->length= field_length;
1044
1003
      }
1045
 
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
 
1004
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
1046
1005
    }
1047
1006
 
1048
1007
    sql_field->create_length_to_internal_length();
1049
 
    if (prepare_blob_field(thd, sql_field))
 
1008
    if (prepare_blob_field(session, sql_field))
1050
1009
      return(true);
1051
1010
 
1052
1011
    if (!(sql_field->flags & NOT_NULL_FLAG))
1088
1047
          sql_field->decimals=          dup_field->decimals;
1089
1048
          sql_field->create_length_to_internal_length();
1090
1049
          sql_field->unireg_check=      dup_field->unireg_check;
1091
 
          /* 
 
1050
          /*
1092
1051
            We're making one field from two, the result field will have
1093
1052
            dup_field->flags as flags. If we've incremented null_fields
1094
1053
            because of sql_field->flags, decrement it back.
1119
1078
  {
1120
1079
    assert(sql_field->charset != 0);
1121
1080
 
1122
 
    if (prepare_create_field(sql_field, &blob_columns, 
 
1081
    if (prepare_create_field(sql_field, &blob_columns,
1123
1082
                             &timestamps, &timestamps_with_niladic,
1124
 
                             file->ha_table_flags()))
 
1083
                             cursor->ha_table_flags()))
1125
1084
      return(true);
1126
 
    if (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1127
 
      create_info->varchar= true;
1128
1085
    sql_field->offset= record_offset;
1129
1086
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1130
1087
      auto_increment++;
1131
 
    record_offset+= sql_field->pack_length;
1132
1088
  }
1133
1089
  if (timestamps_with_niladic > 1)
1134
1090
  {
1142
1098
    return(true);
1143
1099
  }
1144
1100
  if (auto_increment &&
1145
 
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
 
1101
      (cursor->ha_table_flags() & HA_NO_AUTO_INCREMENT))
1146
1102
  {
1147
1103
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
1148
1104
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
1149
1105
    return(true);
1150
1106
  }
1151
1107
 
1152
 
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
 
1108
  if (blob_columns && (cursor->ha_table_flags() & HA_NO_BLOBS))
1153
1109
  {
1154
1110
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
1155
1111
               MYF(0));
1160
1116
 
1161
1117
  List_iterator<Key> key_iterator(alter_info->key_list);
1162
1118
  List_iterator<Key> key_iterator2(alter_info->key_list);
1163
 
  uint key_parts=0, fk_key_count=0;
 
1119
  uint32_t key_parts=0, fk_key_count=0;
1164
1120
  bool primary_key=0,unique_key=0;
1165
1121
  Key *key, *key2;
1166
 
  uint tmp, key_number;
 
1122
  uint32_t tmp, key_number;
1167
1123
  /* special marker for keys to be ignored */
1168
1124
  static char ignore_key[1];
1169
1125
 
1175
1131
    if (key->type == Key::FOREIGN_KEY)
1176
1132
    {
1177
1133
      fk_key_count++;
 
1134
      if (((Foreign_key *)key)->validate(alter_info->create_list))
 
1135
        return true;
1178
1136
      Foreign_key *fk_key= (Foreign_key*) key;
1179
1137
      if (fk_key->ref_columns.elements &&
1180
1138
          fk_key->ref_columns.elements != fk_key->columns.elements)
1188
1146
      continue;
1189
1147
    }
1190
1148
    (*key_count)++;
1191
 
    tmp=file->max_key_parts();
 
1149
    tmp=cursor->max_key_parts();
1192
1150
    if (key->columns.elements > tmp)
1193
1151
    {
1194
1152
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
1231
1189
    else
1232
1190
      (*key_count)--;
1233
1191
    if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
1234
 
        !my_strcasecmp(system_charset_info,key->name.str, primary_key_name))
 
1192
        is_primary_key_name(key->name.str))
1235
1193
    {
1236
1194
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
1237
1195
      return(true);
1238
1196
    }
1239
1197
  }
1240
 
  tmp=file->max_keys();
 
1198
  tmp=cursor->max_keys();
1241
1199
  if (*key_count > tmp)
1242
1200
  {
1243
1201
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
1253
1211
  key_number=0;
1254
1212
  for (; (key=key_iterator++) ; key_number++)
1255
1213
  {
1256
 
    uint key_length=0;
 
1214
    uint32_t key_length=0;
1257
1215
    Key_part_spec *column;
1258
1216
 
1259
1217
    if (key->name.str == ignore_key)
1292
1250
    */
1293
1251
    key_info->block_size= (key->key_create_info.block_size ?
1294
1252
                           key->key_create_info.block_size :
1295
 
                           create_info->key_block_size);
 
1253
                           create_proto->options().key_block_size());
1296
1254
 
1297
1255
    if (key_info->block_size)
1298
1256
      key_info->flags|= HA_USES_BLOCK_SIZE;
1299
1257
 
1300
 
    uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
 
1258
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
1301
1259
                                           key->key_create_info.comment.str,
1302
1260
                                           key->key_create_info.comment.str +
1303
1261
                                           key->key_create_info.comment.length,
1307
1265
    {
1308
1266
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
1309
1267
               key->key_create_info.comment.str,"INDEX COMMENT",
1310
 
               (uint) INDEX_COMMENT_MAXLEN);
1311
 
      return(-1);
 
1268
               (uint32_t) INDEX_COMMENT_MAXLEN);
 
1269
      return -1;
1312
1270
    }
1313
1271
 
1314
1272
    key_info->comment.length= key->key_create_info.comment.length;
1319
1277
    }
1320
1278
 
1321
1279
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
1322
 
    for (uint column_nr=0 ; (column=cols++) ; column_nr++)
 
1280
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
1323
1281
    {
1324
 
      uint length;
 
1282
      uint32_t length;
1325
1283
      Key_part_spec *dup_column;
1326
1284
 
1327
1285
      it.rewind();
1349
1307
      }
1350
1308
      cols2.rewind();
1351
1309
      {
1352
 
        column->length*= sql_field->charset->mbmaxlen;
 
1310
        column->length*= sql_field->charset->mbmaxlen;
1353
1311
 
1354
 
        if (f_is_blob(sql_field->pack_flag))
1355
 
        {
1356
 
          if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
1357
 
          {
1358
 
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
1359
 
            return(true);
1360
 
          }
1361
 
          if (!column->length)
1362
 
          {
1363
 
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
1364
 
            return(true);
1365
 
          }
1366
 
        }
1367
 
        if (!(sql_field->flags & NOT_NULL_FLAG))
1368
 
        {
1369
 
          if (key->type == Key::PRIMARY)
1370
 
          {
1371
 
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
1372
 
            sql_field->flags|= NOT_NULL_FLAG;
1373
 
            sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
 
1312
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
1313
        {
 
1314
          if (! (cursor->ha_table_flags() & HA_CAN_INDEX_BLOBS))
 
1315
          {
 
1316
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
1317
            return true;
 
1318
          }
 
1319
          if (! column->length)
 
1320
          {
 
1321
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
1322
            return true;
 
1323
          }
 
1324
        }
 
1325
        if (! (sql_field->flags & NOT_NULL_FLAG))
 
1326
        {
 
1327
          if (key->type == Key::PRIMARY)
 
1328
          {
 
1329
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
1330
            sql_field->flags|= NOT_NULL_FLAG;
1374
1331
            null_fields--;
1375
 
          }
1376
 
          else
 
1332
          }
 
1333
          else
1377
1334
          {
1378
1335
            key_info->flags|= HA_NULL_PART_KEY;
1379
 
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
 
1336
            if (! (cursor->ha_table_flags() & HA_NULL_IN_KEY))
1380
1337
            {
1381
1338
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1382
 
              return(true);
 
1339
              return true;
1383
1340
            }
1384
1341
          }
1385
 
        }
1386
 
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1387
 
        {
1388
 
          if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
1389
 
            auto_increment--;                   // Field is used
1390
 
        }
 
1342
        }
 
1343
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
1344
        {
 
1345
          if (column_nr == 0 || (cursor->ha_table_flags() & HA_AUTO_PART_KEY))
 
1346
            auto_increment--;                   // Field is used
 
1347
        }
1391
1348
      }
1392
1349
 
1393
1350
      key_part_info->fieldnr= field;
1397
1354
 
1398
1355
      if (column->length)
1399
1356
      {
1400
 
        if (f_is_blob(sql_field->pack_flag))
 
1357
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1401
1358
        {
1402
1359
          if ((length=column->length) > max_key_length ||
1403
 
              length > file->max_key_part_length())
 
1360
              length > cursor->max_key_part_length())
1404
1361
          {
1405
 
            length=min(max_key_length, file->max_key_part_length());
 
1362
            length= min(max_key_length, cursor->max_key_part_length());
1406
1363
            if (key->type == Key::MULTIPLE)
1407
1364
            {
1408
1365
              /* not a critical problem */
1409
1366
              char warn_buff[DRIZZLE_ERRMSG_SIZE];
1410
1367
              snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1411
1368
                       length);
1412
 
              push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1369
              push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1413
1370
                           ER_TOO_LONG_KEY, warn_buff);
1414
1371
              /* Align key length to multibyte char boundary */
1415
1372
              length-= length % sql_field->charset->mbmaxlen;
1422
1379
          }
1423
1380
        }
1424
1381
        else if ((column->length > length ||
1425
 
                   !Field::type_can_have_key_part (sql_field->sql_type) ||
1426
 
                   ((f_is_packed(sql_field->pack_flag) ||
1427
 
                     ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
1428
 
                      (key_info->flags & HA_NOSAME))) &&
1429
 
                    column->length != length)))
 
1382
            ! Field::type_can_have_key_part(sql_field->sql_type)))
1430
1383
        {
1431
1384
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1432
1385
          return(true);
1433
1386
        }
1434
 
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
 
1387
        else if (!(cursor->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
1435
1388
          length=column->length;
1436
1389
      }
1437
1390
      else if (length == 0)
1439
1392
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1440
1393
          return(true);
1441
1394
      }
1442
 
      if (length > file->max_key_part_length())
 
1395
      if (length > cursor->max_key_part_length())
1443
1396
      {
1444
 
        length= file->max_key_part_length();
 
1397
        length= cursor->max_key_part_length();
1445
1398
        if (key->type == Key::MULTIPLE)
1446
1399
        {
1447
1400
          /* not a critical problem */
1448
1401
          char warn_buff[DRIZZLE_ERRMSG_SIZE];
1449
1402
          snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1450
1403
                   length);
1451
 
          push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1404
          push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1452
1405
                       ER_TOO_LONG_KEY, warn_buff);
1453
1406
          /* Align key length to multibyte char boundary */
1454
1407
          length-= length % sql_field->charset->mbmaxlen;
1464
1417
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1465
1418
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1466
1419
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1467
 
            sql_field->pack_flag & FIELDFLAG_BLOB)))
 
1420
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1468
1421
      {
1469
 
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
 
1422
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1470
1423
            sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1471
 
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
1472
 
        else
1473
 
          key_info->flags|= HA_PACK_KEY;
 
1424
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
1425
        else
 
1426
          key_info->flags|= HA_PACK_KEY;
1474
1427
      }
1475
1428
      /* Check if the key segment is partial, set the key flag accordingly */
1476
1429
      if (length != sql_field->key_length)
1490
1443
                       MYF(0));
1491
1444
            return(true);
1492
1445
          }
1493
 
          key_name=primary_key_name;
 
1446
          static const char pkey_name[]= "PRIMARY";
 
1447
          key_name=pkey_name;
1494
1448
          primary_key=1;
1495
1449
        }
1496
1450
        else if (!(key_name= key->name.str))
1520
1474
    key_info++;
1521
1475
  }
1522
1476
  if (!unique_key && !primary_key &&
1523
 
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
 
1477
      (cursor->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
1524
1478
  {
1525
1479
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1526
1480
    return(true);
1531
1485
    return(true);
1532
1486
  }
1533
1487
  /* Sort keys in optimized order */
1534
 
  my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
 
1488
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1535
1489
           (qsort_cmp) sort_keys);
1536
 
  create_info->null_bits= null_fields;
1537
1490
 
1538
1491
  /* Check fields. */
1539
1492
  it.rewind();
1541
1494
  {
1542
1495
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1543
1496
 
1544
 
    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
 
1497
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1545
1498
        !sql_field->def &&
1546
1499
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1547
1500
        (sql_field->flags & NOT_NULL_FLAG) &&
1569
1522
  return(false);
1570
1523
}
1571
1524
 
1572
 
 
1573
 
/*
1574
 
  Set table default charset, if not set
1575
 
 
1576
 
  SYNOPSIS
1577
 
    set_table_default_charset()
1578
 
    create_info        Table create information
1579
 
 
1580
 
  DESCRIPTION
1581
 
    If the table character set was not given explicitely,
1582
 
    let's fetch the database default character set and
1583
 
    apply it to the table.
1584
 
*/
1585
 
 
1586
 
static void set_table_default_charset(THD *thd,
1587
 
                                      HA_CREATE_INFO *create_info, char *db)
1588
 
{
1589
 
  /*
1590
 
    If the table character set was not given explicitly,
1591
 
    let's fetch the database default character set and
1592
 
    apply it to the table.
1593
 
  */
1594
 
  if (!create_info->default_table_charset)
1595
 
  {
1596
 
    HA_CREATE_INFO db_info;
1597
 
 
1598
 
    load_db_opt_by_name(thd, db, &db_info);
1599
 
 
1600
 
    create_info->default_table_charset= db_info.default_table_charset;
1601
 
  }
1602
 
}
1603
 
 
1604
 
 
1605
1525
/*
1606
1526
  Extend long VARCHAR fields to blob & prepare field if it's a blob
1607
1527
 
1615
1535
        In this case the error is given
1616
1536
*/
1617
1537
 
1618
 
static bool prepare_blob_field(THD *thd __attribute__((unused)),
1619
 
                               Create_field *sql_field)
 
1538
static bool prepare_blob_field(Session *,
 
1539
                               CreateField *sql_field)
1620
1540
{
1621
1541
 
1622
1542
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
1624
1544
  {
1625
1545
    my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1626
1546
             MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1627
 
    return(1);
 
1547
    return 1;
1628
1548
  }
1629
 
    
 
1549
 
1630
1550
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1631
1551
  {
1632
1552
    if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1633
1553
    {
1634
1554
      /* The user has given a length to the blob column */
1635
 
      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1636
1555
      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1637
1556
    }
1638
1557
    sql_field->length= 0;
1639
1558
  }
1640
 
  return(0);
1641
 
}
1642
 
 
1643
 
 
1644
 
/*
1645
 
  Preparation of Create_field for SP function return values.
1646
 
  Based on code used in the inner loop of mysql_prepare_create_table()
1647
 
  above.
1648
 
 
1649
 
  SYNOPSIS
1650
 
    sp_prepare_create_field()
1651
 
    thd                 Thread object
1652
 
    sql_field           Field to prepare
1653
 
 
1654
 
  DESCRIPTION
1655
 
    Prepares the field structures for field creation.
1656
 
 
1657
 
*/
1658
 
 
1659
 
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
1660
 
{
1661
 
  if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
1662
 
  {
1663
 
    uint32_t field_length, dummy;
1664
 
    /* DRIZZLE_TYPE_ENUM */
1665
 
    {
1666
 
      calculate_interval_lengths(sql_field->charset,
1667
 
                                 sql_field->interval,
1668
 
                                 &field_length, &dummy);
1669
 
      sql_field->length= field_length;
1670
 
    }
1671
 
    set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
1672
 
  }
1673
 
 
1674
 
  sql_field->create_length_to_internal_length();
1675
 
  assert(sql_field->def == 0);
1676
 
  /* Can't go wrong as sql_field->def is not defined */
1677
 
  (void) prepare_blob_field(thd, sql_field);
1678
 
}
1679
 
 
1680
 
 
1681
 
/*
 
1559
  return 0;
 
1560
}
 
1561
 
 
1562
 
 
1563
/*
 
1564
  Ignore the name of this function... it locks :(
 
1565
 
1682
1566
  Create a table
1683
1567
 
1684
1568
  SYNOPSIS
1685
1569
    mysql_create_table_no_lock()
1686
 
    thd                 Thread object
 
1570
    session                     Thread object
1687
1571
    db                  Database
1688
1572
    table_name          Table name
1689
1573
    create_info         Create information (like MAX_ROWS)
1690
1574
    fields              List of fields to create
1691
1575
    keys                List of keys to create
1692
1576
    internal_tmp_table  Set to 1 if this is an internal temporary table
1693
 
                        (From ALTER TABLE)
1694
 
    select_field_count  
 
1577
                        (From ALTER Table)
 
1578
    select_field_count
1695
1579
 
1696
1580
  DESCRIPTION
1697
1581
    If one creates a temporary table, this is automatically opened
1701
1585
    that concurrent operations won't intervene. mysql_create_table()
1702
1586
    is a wrapper that can be used for this.
1703
1587
 
1704
 
    no_log is needed for the case of CREATE ... SELECT,
1705
 
    as the logging will be done later in sql_insert.cc
1706
 
    select_field_count is also used for CREATE ... SELECT,
1707
 
    and must be zero for standard create of table.
1708
 
 
1709
1588
  RETURN VALUES
1710
1589
    false OK
1711
1590
    true  error
1712
1591
*/
1713
1592
 
1714
 
bool mysql_create_table_no_lock(THD *thd,
 
1593
bool mysql_create_table_no_lock(Session *session,
1715
1594
                                const char *db, const char *table_name,
1716
1595
                                HA_CREATE_INFO *create_info,
1717
 
                                Alter_info *alter_info,
 
1596
                                message::Table *table_proto,
 
1597
                                AlterInfo *alter_info,
1718
1598
                                bool internal_tmp_table,
1719
 
                                uint select_field_count)
 
1599
                                uint32_t select_field_count)
1720
1600
{
1721
1601
  char          path[FN_REFLEN];
1722
 
  uint          path_length;
1723
 
  const char    *alias;
 
1602
  uint32_t          path_length;
1724
1603
  uint          db_options, key_count;
1725
1604
  KEY           *key_info_buffer;
1726
 
  handler       *file;
 
1605
  Cursor        *cursor;
1727
1606
  bool          error= true;
 
1607
  TableShare share;
 
1608
 
1728
1609
  /* Check for duplicate fields and check type of table to create */
1729
1610
  if (!alter_info->create_list.elements)
1730
1611
  {
1731
1612
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1732
1613
               MYF(0));
1733
 
    return(true);
 
1614
    return true;
1734
1615
  }
1735
 
  if (check_engine(thd, table_name, create_info))
1736
 
    return(true);
 
1616
  assert(strcmp(table_name,table_proto->name().c_str())==0);
 
1617
  if (check_engine(session, table_name, create_info))
 
1618
    return true;
1737
1619
  db_options= create_info->table_options;
1738
1620
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
1739
1621
    db_options|=HA_OPTION_PACK_RECORD;
1740
 
  alias= table_case_name(create_info, table_name);
1741
 
  if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
1742
 
                              create_info->db_type)))
 
1622
  if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1743
1623
  {
1744
 
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1745
 
    return(true);
 
1624
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
 
1625
    return true;
1746
1626
  }
1747
1627
 
1748
 
  set_table_default_charset(thd, create_info, (char*) db);
 
1628
  set_table_default_charset(create_info, (char*) db);
1749
1629
 
1750
 
  if (mysql_prepare_create_table(thd, create_info, alter_info,
 
1630
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1751
1631
                                 internal_tmp_table,
1752
 
                                 &db_options, file,
1753
 
                          &key_info_buffer, &key_count,
1754
 
                          select_field_count))
 
1632
                                 &db_options, cursor,
 
1633
                                 &key_info_buffer, &key_count,
 
1634
                                 select_field_count))
1755
1635
    goto err;
1756
1636
 
1757
1637
      /* Check if table exists */
1758
1638
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1759
1639
  {
1760
 
    path_length= build_tmptable_filename(thd, path, sizeof(path));
1761
 
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
 
1640
    path_length= build_tmptable_filename(session, path, sizeof(path));
1762
1641
  }
1763
 
  else  
 
1642
  else
1764
1643
  {
1765
1644
 #ifdef FN_DEVCHAR
1766
1645
    /* check if the table name contains FN_DEVCHAR when defined */
1767
 
    if (strchr(alias, FN_DEVCHAR))
 
1646
    if (strchr(table_name, FN_DEVCHAR))
1768
1647
    {
1769
 
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1770
 
      return(true);
 
1648
      my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
 
1649
      return true;
1771
1650
    }
1772
1651
#endif
1773
 
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1774
 
                                      internal_tmp_table ? FN_IS_TMP : 0);
 
1652
    path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
1775
1653
  }
1776
1654
 
1777
1655
  /* Check if table already exists */
1778
1656
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1779
 
      find_temporary_table(thd, db, table_name))
 
1657
      session->find_temporary_table(db, table_name))
1780
1658
  {
1781
1659
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1782
1660
    {
1783
1661
      create_info->table_existed= 1;            // Mark that table existed
1784
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1662
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1785
1663
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1786
 
                          alias);
 
1664
                          table_name);
1787
1665
      error= 0;
1788
1666
      goto err;
1789
1667
    }
1790
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
 
1668
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1791
1669
    goto err;
1792
1670
  }
1793
1671
 
1794
 
  VOID(pthread_mutex_lock(&LOCK_open));
 
1672
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1795
1673
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1796
1674
  {
1797
 
    if (!access(path,F_OK))
 
1675
    if (plugin::StorageEngine::getTableDefinition(*session, path, db, table_name, internal_tmp_table)==EEXIST)
1798
1676
    {
1799
1677
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1800
 
        goto warn;
1801
 
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1678
      {
 
1679
        error= false;
 
1680
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1681
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1682
                            table_name);
 
1683
        create_info->table_existed= 1;          // Mark that table existed
 
1684
      }
 
1685
      else 
 
1686
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1687
 
1802
1688
      goto unlock_and_end;
1803
1689
    }
1804
1690
    /*
1805
1691
      We don't assert here, but check the result, because the table could be
1806
1692
      in the table definition cache and in the same time the .frm could be
1807
1693
      missing from the disk, in case of manual intervention which deletes
1808
 
      the .frm file. The user has to use FLUSH TABLES; to clear the cache.
 
1694
      the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1809
1695
      Then she could create the table. This case is pretty obscure and
1810
1696
      therefore we don't introduce a new error message only for it.
1811
1697
    */
1812
 
    if (get_cached_table_share(db, alias))
 
1698
    if (TableShare::getShare(db, table_name))
1813
1699
    {
1814
1700
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1815
1701
      goto unlock_and_end;
1823
1709
    unless user specified CREATE TABLE IF EXISTS
1824
1710
    The LOCK_open mutex has been locked to make sure no
1825
1711
    one else is attempting to discover the table. Since
1826
 
    it's not on disk as a frm file, no one could be using it!
 
1712
    it's not on disk as a frm cursor, no one could be using it!
1827
1713
  */
1828
1714
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1829
1715
  {
1830
1716
    bool create_if_not_exists =
1831
1717
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1832
 
    int retcode = ha_table_exists_in_engine(thd, db, table_name);
 
1718
 
 
1719
    char table_path[FN_REFLEN];
 
1720
    uint32_t          table_path_length;
 
1721
 
 
1722
    table_path_length= build_table_filename(table_path, sizeof(table_path),
 
1723
                                            db, table_name, false);
 
1724
 
 
1725
    int retcode= plugin::StorageEngine::getTableDefinition(*session, table_path, db, table_name, false);
1833
1726
    switch (retcode)
1834
1727
    {
1835
 
      case HA_ERR_NO_SUCH_TABLE:
 
1728
      case ENOENT:
1836
1729
        /* Normal case, no table exists. we can go and create it */
1837
1730
        break;
1838
 
      case HA_ERR_TABLE_EXIST:
1839
 
 
1840
 
      if (create_if_not_exists)
1841
 
        goto warn;
1842
 
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1843
 
      goto unlock_and_end;
1844
 
        break;
 
1731
      case EEXIST:
 
1732
        if (create_if_not_exists)
 
1733
        {
 
1734
          error= false;
 
1735
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1736
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1737
                              table_name);
 
1738
          create_info->table_existed= 1;                // Mark that table existed
 
1739
          goto unlock_and_end;
 
1740
        }
 
1741
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1742
        goto unlock_and_end;
1845
1743
      default:
1846
1744
        my_error(retcode, MYF(0),table_name);
1847
1745
        goto unlock_and_end;
1848
1746
    }
1849
1747
  }
1850
1748
 
1851
 
  thd_proc_info(thd, "creating table");
 
1749
  session->set_proc_info("creating table");
1852
1750
  create_info->table_existed= 0;                // Mark that table is created
1853
1751
 
1854
 
#ifdef HAVE_READLINK
1855
 
  if (test_if_data_home_dir(create_info->data_file_name))
1856
 
  {
1857
 
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
1858
 
    goto unlock_and_end;
1859
 
  }
1860
 
  if (test_if_data_home_dir(create_info->index_file_name))
1861
 
  {
1862
 
    my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
1863
 
    goto unlock_and_end;
1864
 
  }
1865
 
 
1866
 
  if (!my_use_symdir)
1867
 
#endif /* HAVE_READLINK */
1868
 
  {
1869
 
    if (create_info->data_file_name)
1870
 
      push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1871
 
                   "DATA DIRECTORY option ignored");
1872
 
    if (create_info->index_file_name)
1873
 
      push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1874
 
                   "INDEX DIRECTORY option ignored");
1875
 
    create_info->data_file_name= create_info->index_file_name= 0;
1876
 
  }
1877
1752
  create_info->table_options=db_options;
1878
1753
 
1879
 
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1880
 
  if (rea_create_table(thd, path, db, table_name,
 
1754
  if (rea_create_table(session, path, db, table_name,
 
1755
                       table_proto,
1881
1756
                       create_info, alter_info->create_list,
1882
 
                       key_count, key_info_buffer, file))
 
1757
                       key_count, key_info_buffer))
1883
1758
    goto unlock_and_end;
1884
1759
 
1885
1760
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1886
1761
  {
1887
1762
    /* Open table and put in temporary table list */
1888
 
    if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
 
1763
    if (!(session->open_temporary_table(path, db, table_name, 1)))
1889
1764
    {
1890
 
      (void) rm_temporary_table(create_info->db_type, path, false);
 
1765
      (void) session->rm_temporary_table(create_info->db_type, path);
1891
1766
      goto unlock_and_end;
1892
1767
    }
1893
 
    thd->thread_specific_used= true;
1894
1768
  }
1895
1769
 
1896
1770
  /*
1901
1775
    Otherwise, the statement shall be binlogged.
1902
1776
   */
1903
1777
  if (!internal_tmp_table &&
1904
 
      (!thd->current_stmt_binlog_row_based ||
1905
 
       (thd->current_stmt_binlog_row_based &&
1906
 
        !(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1907
 
    write_bin_log(thd, true, thd->query, thd->query_length);
 
1778
      ((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
 
1779
    write_bin_log(session, session->query, session->query_length);
1908
1780
  error= false;
1909
1781
unlock_and_end:
1910
 
  VOID(pthread_mutex_unlock(&LOCK_open));
 
1782
  pthread_mutex_unlock(&LOCK_open);
1911
1783
 
1912
1784
err:
1913
 
  thd_proc_info(thd, "After create");
1914
 
  delete file;
 
1785
  session->set_proc_info("After create");
 
1786
  delete cursor;
1915
1787
  return(error);
1916
 
 
1917
 
warn:
1918
 
  error= false;
1919
 
  push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1920
 
                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1921
 
                      alias);
1922
 
  create_info->table_existed= 1;                // Mark that table existed
1923
 
  goto unlock_and_end;
1924
1788
}
1925
1789
 
1926
1790
 
1928
1792
  Database locking aware wrapper for mysql_create_table_no_lock(),
1929
1793
*/
1930
1794
 
1931
 
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
 
1795
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1932
1796
                        HA_CREATE_INFO *create_info,
1933
 
                        Alter_info *alter_info,
 
1797
                        message::Table *table_proto,
 
1798
                        AlterInfo *alter_info,
1934
1799
                        bool internal_tmp_table,
1935
 
                        uint select_field_count)
 
1800
                        uint32_t select_field_count)
1936
1801
{
1937
 
  TABLE *name_lock= 0;
 
1802
  Table *name_lock= NULL;
1938
1803
  bool result;
1939
1804
 
1940
 
  /* Wait for any database locks */
1941
 
  pthread_mutex_lock(&LOCK_lock_db);
1942
 
  while (!thd->killed &&
1943
 
         hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
1944
 
  {
1945
 
    wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
1946
 
    pthread_mutex_lock(&LOCK_lock_db);
1947
 
  }
1948
 
 
1949
 
  if (thd->killed)
1950
 
  {
1951
 
    pthread_mutex_unlock(&LOCK_lock_db);
1952
 
    return(true);
1953
 
  }
1954
 
  creating_table++;
1955
 
  pthread_mutex_unlock(&LOCK_lock_db);
1956
 
 
1957
1805
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1958
1806
  {
1959
 
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
1807
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
1960
1808
    {
1961
1809
      result= true;
1962
1810
      goto unlock;
1963
1811
    }
1964
 
    if (!name_lock)
 
1812
    if (name_lock == NULL)
1965
1813
    {
1966
1814
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1967
1815
      {
1968
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1816
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1969
1817
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1970
1818
                            table_name);
1971
1819
        create_info->table_existed= 1;
1980
1828
    }
1981
1829
  }
1982
1830
 
1983
 
  result= mysql_create_table_no_lock(thd, db, table_name, create_info,
 
1831
  result= mysql_create_table_no_lock(session, db, table_name, create_info,
 
1832
                                     table_proto,
1984
1833
                                     alter_info,
1985
1834
                                     internal_tmp_table,
1986
1835
                                     select_field_count);
1988
1837
unlock:
1989
1838
  if (name_lock)
1990
1839
  {
1991
 
    pthread_mutex_lock(&LOCK_open);
1992
 
    unlink_open_table(thd, name_lock, false);
 
1840
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
 
1841
    session->unlink_open_table(name_lock);
1993
1842
    pthread_mutex_unlock(&LOCK_open);
1994
1843
  }
1995
 
  pthread_mutex_lock(&LOCK_lock_db);
1996
 
  if (!--creating_table && creating_database)
1997
 
    pthread_cond_signal(&COND_refresh);
1998
 
  pthread_mutex_unlock(&LOCK_lock_db);
 
1844
 
1999
1845
  return(result);
2000
1846
}
2001
1847
 
2020
1866
  char buff[MAX_FIELD_NAME],*buff_end;
2021
1867
 
2022
1868
  if (!check_if_keyname_exists(field_name,start,end) &&
2023
 
      my_strcasecmp(system_charset_info,field_name,primary_key_name))
 
1869
      !is_primary_key_name(field_name))
2024
1870
    return (char*) field_name;                  // Use fieldname
2025
 
  buff_end=strmake(buff,field_name, sizeof(buff)-4);
 
1871
 
 
1872
  buff_end= strncpy(buff, field_name, sizeof(buff)-4);
 
1873
  buff_end+= strlen(buff);
2026
1874
 
2027
1875
  /*
2028
1876
    Only 3 chars + '\0' left, so need to limit to 2 digit
2029
1877
    This is ok as we can't have more than 100 keys anyway
2030
1878
  */
2031
 
  for (uint i=2 ; i< 100; i++)
 
1879
  for (uint32_t i=2 ; i< 100; i++)
2032
1880
  {
2033
1881
    *buff_end= '_';
2034
1882
    int10_to_str(i, buff_end+1, 10);
2043
1891
** Alter a table definition
2044
1892
****************************************************************************/
2045
1893
 
2046
 
 
2047
1894
/*
2048
1895
  Rename a table.
2049
1896
 
2050
1897
  SYNOPSIS
2051
1898
    mysql_rename_table()
2052
 
      base                      The handlerton handle.
 
1899
      base                      The plugin::StorageEngine handle.
2053
1900
      old_db                    The old database name.
2054
1901
      old_name                  The old table name.
2055
1902
      new_db                    The new database name.
2057
1904
      flags                     flags for build_table_filename().
2058
1905
                                FN_FROM_IS_TMP old_name is temporary.
2059
1906
                                FN_TO_IS_TMP   new_name is temporary.
2060
 
                                NO_FRM_RENAME  Don't rename the FRM file
 
1907
                                NO_FRM_RENAME  Don't rename the FRM cursor
2061
1908
                                but only the table in the storage engine.
2062
1909
 
2063
1910
  RETURN
2066
1913
*/
2067
1914
 
2068
1915
bool
2069
 
mysql_rename_table(handlerton *base, const char *old_db,
 
1916
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
2070
1917
                   const char *old_name, const char *new_db,
2071
 
                   const char *new_name, uint flags)
 
1918
                   const char *new_name, uint32_t flags)
2072
1919
{
2073
 
  THD *thd= current_thd;
2074
 
  char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
 
1920
  Session *session= current_session;
 
1921
  char from[FN_REFLEN], to[FN_REFLEN];
2075
1922
  char *from_base= from, *to_base= to;
2076
 
  char tmp_name[NAME_LEN+1];
2077
 
  handler *file;
2078
 
  int error=0;
2079
 
 
2080
 
  file= (base == NULL ? 0 :
2081
 
         get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
2082
 
 
2083
 
  build_table_filename(from, sizeof(from), old_db, old_name, "",
 
1923
  int error= 0;
 
1924
 
 
1925
  assert(base);
 
1926
 
 
1927
  build_table_filename(from, sizeof(from), old_db, old_name,
2084
1928
                       flags & FN_FROM_IS_TMP);
2085
 
  build_table_filename(to, sizeof(to), new_db, new_name, "",
 
1929
  build_table_filename(to, sizeof(to), new_db, new_name,
2086
1930
                       flags & FN_TO_IS_TMP);
2087
1931
 
2088
 
  /*
2089
 
    If lower_case_table_names == 2 (case-preserving but case-insensitive
2090
 
    file system) and the storage is not HA_FILE_BASED, we need to provide
2091
 
    a lowercase file name, but we leave the .frm in mixed case.
2092
 
   */
2093
 
  if (lower_case_table_names == 2 && file &&
2094
 
      !(file->ha_table_flags() & HA_FILE_BASED))
2095
 
  {
2096
 
    stpcpy(tmp_name, old_name);
2097
 
    my_casedn_str(files_charset_info, tmp_name);
2098
 
    build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "",
2099
 
                         flags & FN_FROM_IS_TMP);
2100
 
    from_base= lc_from;
2101
 
 
2102
 
    stpcpy(tmp_name, new_name);
2103
 
    my_casedn_str(files_charset_info, tmp_name);
2104
 
    build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "",
2105
 
                         flags & FN_TO_IS_TMP);
2106
 
    to_base= lc_to;
2107
 
  }
2108
 
  if (!file || !(error=file->ha_rename_table(from_base, to_base)))
2109
 
  {
2110
 
    if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
 
1932
  if (!(error= base->renameTable(session, from_base, to_base)))
 
1933
  {
 
1934
    if(!(flags & NO_FRM_RENAME)
 
1935
       && base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1936
       && rename_table_proto_file(from_base, to_base))
2111
1937
    {
2112
 
      error=my_errno;
2113
 
      /* Restore old file name */
2114
 
      if (file)
2115
 
        file->ha_rename_table(to_base, from_base);
 
1938
      error= my_errno;
 
1939
      base->renameTable(session, to_base, from_base);
2116
1940
    }
2117
1941
  }
2118
 
  delete file;
 
1942
 
2119
1943
  if (error == HA_ERR_WRONG_COMMAND)
2120
 
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
 
1944
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
2121
1945
  else if (error)
2122
1946
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
2123
1947
  return(error != 0);
2129
1953
 
2130
1954
  SYNOPSIS
2131
1955
    wait_while_table_is_used()
2132
 
    thd                 Thread handler
 
1956
    session                     Thread Cursor
2133
1957
    table               Table to remove from cache
2134
1958
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
2135
1959
                        HA_EXTRA_FORCE_REOPEN if table is not be used
2143
1967
    Win32 clients must also have a WRITE LOCK on the table !
2144
1968
*/
2145
1969
 
2146
 
void wait_while_table_is_used(THD *thd, TABLE *table,
 
1970
void wait_while_table_is_used(Session *session, Table *table,
2147
1971
                              enum ha_extra_function function)
2148
1972
{
2149
1973
 
2150
1974
  safe_mutex_assert_owner(&LOCK_open);
2151
1975
 
2152
 
  VOID(table->file->extra(function));
 
1976
  table->cursor->extra(function);
2153
1977
  /* Mark all tables that are in use as 'old' */
2154
 
  mysql_lock_abort(thd, table, true);   /* end threads waiting on lock */
 
1978
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
2155
1979
 
2156
1980
  /* Wait until all there are no other threads that has this table open */
2157
 
  remove_table_from_cache(thd, table->s->db.str,
 
1981
  remove_table_from_cache(session, table->s->db.str,
2158
1982
                          table->s->table_name.str,
2159
1983
                          RTFC_WAIT_OTHER_THREAD_FLAG);
2160
 
  return;
2161
1984
}
2162
1985
 
2163
1986
/*
2165
1988
 
2166
1989
  SYNOPSIS
2167
1990
    close_cached_table()
2168
 
    thd                 Thread handler
 
1991
    session                     Thread Cursor
2169
1992
    table               Table to remove from cache
2170
1993
 
2171
1994
  NOTES
2177
2000
    Win32 clients must also have a WRITE LOCK on the table !
2178
2001
*/
2179
2002
 
2180
 
void close_cached_table(THD *thd, TABLE *table)
 
2003
void Session::close_cached_table(Table *table)
2181
2004
{
2182
2005
 
2183
 
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
2006
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
2184
2007
  /* Close lock if this is not got with LOCK TABLES */
2185
 
  if (thd->lock)
 
2008
  if (lock)
2186
2009
  {
2187
 
    mysql_unlock_tables(thd, thd->lock);
2188
 
    thd->lock=0;                        // Start locked threads
 
2010
    mysql_unlock_tables(this, lock);
 
2011
    lock= NULL;                 // Start locked threads
2189
2012
  }
2190
2013
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
2191
 
  unlink_open_table(thd, table, true);
 
2014
  unlink_open_table(table);
2192
2015
 
2193
2016
  /* When lock on LOCK_open is freed other threads can continue */
2194
2017
  broadcast_refresh();
2195
 
  return;
2196
 
}
2197
 
 
2198
 
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
2199
 
                             const char* operator_name, const char* errmsg)
2200
 
 
2201
 
{
2202
 
  Protocol *protocol= thd->protocol;
2203
 
  protocol->prepare_for_resend();
2204
 
  protocol->store(table->alias, system_charset_info);
2205
 
  protocol->store((char*) operator_name, system_charset_info);
2206
 
  protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2207
 
  protocol->store(errmsg, system_charset_info);
2208
 
  thd->clear_error();
2209
 
  if (protocol->write())
2210
 
    return -1;
2211
 
  return 1;
2212
 
}
2213
 
 
2214
 
 
2215
 
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
2216
 
                              HA_CHECK_OPT *check_opt)
2217
 
{
2218
 
  int error= 0;
2219
 
  TABLE tmp_table, *table;
2220
 
  TABLE_SHARE *share;
2221
 
  char from[FN_REFLEN],tmp[FN_REFLEN+32];
2222
 
  const char **ext;
2223
 
  struct stat stat_info;
2224
 
 
2225
 
  if (!(check_opt->sql_flags & TT_USEFRM))
2226
 
    return(0);
2227
 
 
2228
 
  if (!(table= table_list->table))              /* if open_ltable failed */
2229
 
  {
2230
 
    char key[MAX_DBKEY_LENGTH];
2231
 
    uint key_length;
2232
 
 
2233
 
    key_length= create_table_def_key(thd, key, table_list, 0);
2234
 
    pthread_mutex_lock(&LOCK_open);
2235
 
    if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
2236
 
                                  &error))))
2237
 
    {
2238
 
      pthread_mutex_unlock(&LOCK_open);
2239
 
      return(0);                                // Can't open frm file
2240
 
    }
2241
 
 
2242
 
    if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
2243
 
    {
2244
 
      release_table_share(share, RELEASE_NORMAL);
2245
 
      pthread_mutex_unlock(&LOCK_open);
2246
 
      return(0);                           // Out of memory
2247
 
    }
2248
 
    table= &tmp_table;
2249
 
    pthread_mutex_unlock(&LOCK_open);
2250
 
  }
2251
 
 
2252
 
  /*
2253
 
    REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
2254
 
  */
2255
 
  if (table->s->tmp_table)
2256
 
  {
2257
 
    error= send_check_errmsg(thd, table_list, "repair",
2258
 
                             "Cannot repair temporary table from .frm file");
2259
 
    goto end;
2260
 
  }
2261
 
 
2262
 
  /*
2263
 
    User gave us USE_FRM which means that the header in the index file is
2264
 
    trashed.
2265
 
    In this case we will try to fix the table the following way:
2266
 
    - Rename the data file to a temporary name
2267
 
    - Truncate the table
2268
 
    - Replace the new data file with the old one
2269
 
    - Run a normal repair using the new index file and the old data file
2270
 
  */
2271
 
 
2272
 
  /*
2273
 
    Check if this is a table type that stores index and data separately,
2274
 
    like ISAM or MyISAM. We assume fixed order of engine file name
2275
 
    extentions array. First element of engine file name extentions array
2276
 
    is meta/index file extention. Second element - data file extention. 
2277
 
  */
2278
 
  ext= table->file->bas_ext();
2279
 
  if (!ext[0] || !ext[1])
2280
 
    goto end;                                   // No data file
2281
 
 
2282
 
  // Name of data file
2283
 
  strxmov(from, table->s->normalized_path.str, ext[1], NullS);
2284
 
  if (stat(from, &stat_info))
2285
 
    goto end;                           // Can't use USE_FRM flag
2286
 
 
2287
 
  snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
2288
 
           from, current_pid, thd->thread_id);
2289
 
 
2290
 
  /* If we could open the table, close it */
2291
 
  if (table_list->table)
2292
 
  {
2293
 
    pthread_mutex_lock(&LOCK_open);
2294
 
    close_cached_table(thd, table);
2295
 
    pthread_mutex_unlock(&LOCK_open);
2296
 
  }
2297
 
  if (lock_and_wait_for_table_name(thd,table_list))
2298
 
  {
2299
 
    error= -1;
2300
 
    goto end;
2301
 
  }
2302
 
  if (my_rename(from, tmp, MYF(MY_WME)))
2303
 
  {
2304
 
    pthread_mutex_lock(&LOCK_open);
2305
 
    unlock_table_name(thd, table_list);
2306
 
    pthread_mutex_unlock(&LOCK_open);
2307
 
    error= send_check_errmsg(thd, table_list, "repair",
2308
 
                             "Failed renaming data file");
2309
 
    goto end;
2310
 
  }
2311
 
  if (mysql_truncate(thd, table_list, 1))
2312
 
  {
2313
 
    pthread_mutex_lock(&LOCK_open);
2314
 
    unlock_table_name(thd, table_list);
2315
 
    pthread_mutex_unlock(&LOCK_open);
2316
 
    error= send_check_errmsg(thd, table_list, "repair",
2317
 
                             "Failed generating table from .frm file");
2318
 
    goto end;
2319
 
  }
2320
 
  if (my_rename(tmp, from, MYF(MY_WME)))
2321
 
  {
2322
 
    pthread_mutex_lock(&LOCK_open);
2323
 
    unlock_table_name(thd, table_list);
2324
 
    pthread_mutex_unlock(&LOCK_open);
2325
 
    error= send_check_errmsg(thd, table_list, "repair",
2326
 
                             "Failed restoring .MYD file");
2327
 
    goto end;
2328
 
  }
2329
 
 
2330
 
  /*
2331
 
    Now we should be able to open the partially repaired table
2332
 
    to finish the repair in the handler later on.
2333
 
  */
2334
 
  pthread_mutex_lock(&LOCK_open);
2335
 
  if (reopen_name_locked_table(thd, table_list, true))
2336
 
  {
2337
 
    unlock_table_name(thd, table_list);
2338
 
    pthread_mutex_unlock(&LOCK_open);
2339
 
    error= send_check_errmsg(thd, table_list, "repair",
2340
 
                             "Failed to open partially repaired table");
2341
 
    goto end;
2342
 
  }
2343
 
  pthread_mutex_unlock(&LOCK_open);
2344
 
 
2345
 
end:
2346
 
  if (table == &tmp_table)
2347
 
  {
2348
 
    pthread_mutex_lock(&LOCK_open);
2349
 
    closefrm(table, 1);                         // Free allocated memory
2350
 
    pthread_mutex_unlock(&LOCK_open);
2351
 
  }
2352
 
  return(error);
2353
 
}
2354
 
 
2355
 
 
 
2018
}
2356
2019
 
2357
2020
/*
2358
2021
  RETURN VALUES
2359
2022
    false Message sent to net (admin operation went ok)
2360
 
    true  Message should be sent by caller 
 
2023
    true  Message should be sent by caller
2361
2024
          (admin operation or network communication failed)
2362
2025
*/
2363
 
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
 
2026
static bool mysql_admin_table(Session* session, TableList* tables,
2364
2027
                              HA_CHECK_OPT* check_opt,
2365
2028
                              const char *operator_name,
2366
2029
                              thr_lock_type lock_type,
2367
2030
                              bool open_for_modify,
2368
2031
                              bool no_warnings_for_error,
2369
 
                              uint extra_open_options,
2370
 
                              int (*prepare_func)(THD *, TABLE_LIST *,
 
2032
                              uint32_t extra_open_options,
 
2033
                              int (*prepare_func)(Session *, TableList *,
2371
2034
                                                  HA_CHECK_OPT *),
2372
 
                              int (handler::*operator_func)(THD *,
 
2035
                              int (Cursor::*operator_func)(Session *,
2373
2036
                                                            HA_CHECK_OPT *))
2374
2037
{
2375
 
  TABLE_LIST *table;
2376
 
  SELECT_LEX *select= &thd->lex->select_lex;
 
2038
  TableList *table;
 
2039
  Select_Lex *select= &session->lex->select_lex;
2377
2040
  List<Item> field_list;
2378
2041
  Item *item;
2379
 
  Protocol *protocol= thd->protocol;
2380
 
  LEX *lex= thd->lex;
 
2042
  LEX *lex= session->lex;
2381
2043
  int result_code= 0;
2382
2044
  const CHARSET_INFO * const cs= system_charset_info;
2383
2045
 
2384
 
  if (end_active_trans(thd))
2385
 
    return(1);
 
2046
  if (! session->endActiveTransaction())
 
2047
    return 1;
2386
2048
  field_list.push_back(item = new Item_empty_string("Table",
2387
2049
                                                    NAME_CHAR_LEN * 2,
2388
2050
                                                    cs));
2393
2055
  item->maybe_null = 1;
2394
2056
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
2395
2057
  item->maybe_null = 1;
2396
 
  if (protocol->send_fields(&field_list,
2397
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
2398
 
    return(true);
2399
 
 
2400
 
  mysql_ha_rm_tables(thd, tables, false);
 
2058
  if (session->client->sendFields(&field_list))
 
2059
    return true;
2401
2060
 
2402
2061
  for (table= tables; table; table= table->next_local)
2403
2062
  {
2405
2064
    char* db = table->db;
2406
2065
    bool fatal_error=0;
2407
2066
 
2408
 
    strxmov(table_name, db, ".", table->table_name, NullS);
2409
 
    thd->open_options|= extra_open_options;
 
2067
    sprintf(table_name,"%s.%s",db,table->table_name);
 
2068
    session->open_options|= extra_open_options;
2410
2069
    table->lock_type= lock_type;
2411
2070
    /* open only one table from local list of command */
2412
2071
    {
2413
 
      TABLE_LIST *save_next_global, *save_next_local;
 
2072
      TableList *save_next_global, *save_next_local;
2414
2073
      save_next_global= table->next_global;
2415
2074
      table->next_global= 0;
2416
2075
      save_next_local= table->next_local;
2417
2076
      table->next_local= 0;
2418
 
      select->table_list.first= (uchar*)table;
 
2077
      select->table_list.first= (unsigned char*)table;
2419
2078
      /*
2420
2079
        Time zone tables and SP tables can be add to lex->query_tables list,
2421
2080
        so it have to be prepared.
2425
2084
      lex->query_tables= table;
2426
2085
      lex->query_tables_last= &table->next_global;
2427
2086
      lex->query_tables_own_last= 0;
2428
 
      thd->no_warnings_for_error= no_warnings_for_error;
2429
 
      table->required_type=FRMTYPE_TABLE;
 
2087
      session->no_warnings_for_error= no_warnings_for_error;
2430
2088
 
2431
 
      open_and_lock_tables(thd, table);
2432
 
      thd->no_warnings_for_error= 0;
 
2089
      session->openTablesLock(table);
 
2090
      session->no_warnings_for_error= 0;
2433
2091
      table->next_global= save_next_global;
2434
2092
      table->next_local= save_next_local;
2435
 
      thd->open_options&= ~extra_open_options;
 
2093
      session->open_options&= ~extra_open_options;
2436
2094
    }
2437
2095
 
2438
2096
    if (prepare_func)
2439
2097
    {
2440
 
      switch ((*prepare_func)(thd, table, check_opt)) {
 
2098
      switch ((*prepare_func)(session, table, check_opt)) {
2441
2099
      case  1:           // error, message written to net
2442
 
        ha_autocommit_or_rollback(thd, 1);
2443
 
        end_trans(thd, ROLLBACK);
2444
 
        close_thread_tables(thd);
 
2100
        ha_autocommit_or_rollback(session, 1);
 
2101
        session->endTransaction(ROLLBACK);
 
2102
        session->close_thread_tables();
2445
2103
        continue;
2446
2104
      case -1:           // error, message could be written to net
2447
 
        /* purecov: begin inspected */
2448
2105
        goto err;
2449
 
        /* purecov: end */
2450
2106
      default:           // should be 0 otherwise
2451
2107
        ;
2452
2108
      }
2453
2109
    }
2454
2110
 
2455
2111
    /*
2456
 
      CHECK TABLE command is only command where VIEW allowed here and this
 
2112
      CHECK Table command is only command where VIEW allowed here and this
2457
2113
      command use only temporary teble method for VIEWs resolving => there
2458
2114
      can't be VIEW tree substitition of join view => if opening table
2459
 
      succeed then table->table will have real TABLE pointer as value (in
 
2115
      succeed then table->table will have real Table pointer as value (in
2460
2116
      case of join view substitution table->table can be 0, but here it is
2461
2117
      impossible)
2462
2118
    */
2463
2119
    if (!table->table)
2464
2120
    {
2465
 
      if (!thd->warn_list.elements)
2466
 
        push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2121
      if (!session->warn_list.elements)
 
2122
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
2467
2123
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
 
2124
      result_code= HA_ADMIN_CORRUPT;
2468
2125
      goto send_result;
2469
2126
    }
2470
2127
 
2471
2128
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
2472
2129
    {
2473
 
      /* purecov: begin inspected */
2474
2130
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
2475
 
      uint length;
2476
 
      protocol->prepare_for_resend();
2477
 
      protocol->store(table_name, system_charset_info);
2478
 
      protocol->store(operator_name, system_charset_info);
2479
 
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2131
      uint32_t length;
 
2132
      session->client->store(table_name);
 
2133
      session->client->store(operator_name);
 
2134
      session->client->store(STRING_WITH_LEN("error"));
2480
2135
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
2481
2136
                       table_name);
2482
 
      protocol->store(buff, length, system_charset_info);
2483
 
      ha_autocommit_or_rollback(thd, 0);
2484
 
      end_trans(thd, COMMIT);
2485
 
      close_thread_tables(thd);
 
2137
      session->client->store(buff, length);
 
2138
      ha_autocommit_or_rollback(session, 0);
 
2139
      session->endTransaction(COMMIT);
 
2140
      session->close_thread_tables();
2486
2141
      lex->reset_query_tables_list(false);
2487
2142
      table->table=0;                           // For query cache
2488
 
      if (protocol->write())
 
2143
      if (session->client->flush())
2489
2144
        goto err;
2490
2145
      continue;
2491
 
      /* purecov: end */
2492
2146
    }
2493
2147
 
2494
2148
    /* Close all instances of the table to allow repair to rename files */
2495
2149
    if (lock_type == TL_WRITE && table->table->s->version)
2496
2150
    {
2497
 
      pthread_mutex_lock(&LOCK_open);
2498
 
      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 
2151
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2152
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
2499
2153
                                              "Waiting to get writelock");
2500
 
      mysql_lock_abort(thd,table->table, true);
2501
 
      remove_table_from_cache(thd, table->table->s->db.str,
 
2154
      mysql_lock_abort(session,table->table);
 
2155
      remove_table_from_cache(session, table->table->s->db.str,
2502
2156
                              table->table->s->table_name.str,
2503
2157
                              RTFC_WAIT_OTHER_THREAD_FLAG |
2504
2158
                              RTFC_CHECK_KILLED_FLAG);
2505
 
      thd->exit_cond(old_message);
2506
 
      if (thd->killed)
 
2159
      session->exit_cond(old_message);
 
2160
      if (session->killed)
2507
2161
        goto err;
2508
2162
      open_for_modify= 0;
2509
2163
    }
2510
2164
 
2511
 
    if (table->table->s->crashed && operator_func == &handler::ha_check)
 
2165
    if (table->table->s->crashed && operator_func == &Cursor::ha_check)
2512
2166
    {
2513
 
      /* purecov: begin inspected */
2514
 
      protocol->prepare_for_resend();
2515
 
      protocol->store(table_name, system_charset_info);
2516
 
      protocol->store(operator_name, system_charset_info);
2517
 
      protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
2518
 
      protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
2519
 
                      system_charset_info);
2520
 
      if (protocol->write())
 
2167
      session->client->store(table_name);
 
2168
      session->client->store(operator_name);
 
2169
      session->client->store(STRING_WITH_LEN("warning"));
 
2170
      session->client->store(STRING_WITH_LEN("Table is marked as crashed"));
 
2171
      if (session->client->flush())
2521
2172
        goto err;
2522
 
      /* purecov: end */
2523
 
    }
2524
 
 
2525
 
    if (operator_func == &handler::ha_repair &&
2526
 
        !(check_opt->sql_flags & TT_USEFRM))
2527
 
    {
2528
 
      if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
2529
 
          (table->table->file->ha_check_for_upgrade(check_opt) ==
2530
 
           HA_ADMIN_NEEDS_ALTER))
2531
 
      {
2532
 
        ha_autocommit_or_rollback(thd, 1);
2533
 
        close_thread_tables(thd);
2534
 
        tmp_disable_binlog(thd); // binlogging is done by caller if wanted
2535
 
        result_code= mysql_recreate_table(thd, table);
2536
 
        reenable_binlog(thd);
2537
 
        /*
2538
 
          mysql_recreate_table() can push OK or ERROR.
2539
 
          Clear 'OK' status. If there is an error, keep it:
2540
 
          we will store the error message in a result set row 
2541
 
          and then clear.
2542
 
        */
2543
 
        if (thd->main_da.is_ok())
2544
 
          thd->main_da.reset_diagnostics_area();
2545
 
        goto send_result;
2546
 
      }
2547
 
    }
2548
 
 
2549
 
    result_code = (table->table->file->*operator_func)(thd, check_opt);
 
2173
    }
 
2174
 
 
2175
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
2550
2176
 
2551
2177
send_result:
2552
2178
 
2553
2179
    lex->cleanup_after_one_table_open();
2554
 
    thd->clear_error();  // these errors shouldn't get client
 
2180
    session->clear_error();  // these errors shouldn't get client
2555
2181
    {
2556
 
      List_iterator_fast<DRIZZLE_ERROR> it(thd->warn_list);
 
2182
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
2557
2183
      DRIZZLE_ERROR *err;
2558
2184
      while ((err= it++))
2559
2185
      {
2560
 
        protocol->prepare_for_resend();
2561
 
        protocol->store(table_name, system_charset_info);
2562
 
        protocol->store((char*) operator_name, system_charset_info);
2563
 
        protocol->store(warning_level_names[err->level].str,
2564
 
                        warning_level_names[err->level].length,
2565
 
                        system_charset_info);
2566
 
        protocol->store(err->msg, system_charset_info);
2567
 
        if (protocol->write())
 
2186
        session->client->store(table_name);
 
2187
        session->client->store(operator_name);
 
2188
        session->client->store(warning_level_names[err->level].str,
 
2189
                               warning_level_names[err->level].length);
 
2190
        session->client->store(err->msg);
 
2191
        if (session->client->flush())
2568
2192
          goto err;
2569
2193
      }
2570
 
      drizzle_reset_errors(thd, true);
 
2194
      drizzle_reset_errors(session, true);
2571
2195
    }
2572
 
    protocol->prepare_for_resend();
2573
 
    protocol->store(table_name, system_charset_info);
2574
 
    protocol->store(operator_name, system_charset_info);
 
2196
    session->client->store(table_name);
 
2197
    session->client->store(operator_name);
2575
2198
 
2576
2199
send_result_message:
2577
2200
 
2579
2202
    case HA_ADMIN_NOT_IMPLEMENTED:
2580
2203
      {
2581
2204
        char buf[ERRMSGSIZE+20];
2582
 
        uint length=snprintf(buf, ERRMSGSIZE,
 
2205
        uint32_t length=snprintf(buf, ERRMSGSIZE,
2583
2206
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
2584
 
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
2585
 
        protocol->store(buf, length, system_charset_info);
2586
 
      }
2587
 
      break;
2588
 
 
2589
 
    case HA_ADMIN_NOT_BASE_TABLE:
2590
 
      {
2591
 
        char buf[ERRMSGSIZE+20];
2592
 
        uint length= snprintf(buf, ERRMSGSIZE,
2593
 
                              ER(ER_BAD_TABLE_ERROR), table_name);
2594
 
        protocol->store(STRING_WITH_LEN("note"), system_charset_info);
2595
 
        protocol->store(buf, length, system_charset_info);
 
2207
        session->client->store(STRING_WITH_LEN("note"));
 
2208
        session->client->store(buf, length);
2596
2209
      }
2597
2210
      break;
2598
2211
 
2599
2212
    case HA_ADMIN_OK:
2600
 
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
2601
 
      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
 
2213
      session->client->store(STRING_WITH_LEN("status"));
 
2214
      session->client->store(STRING_WITH_LEN("OK"));
2602
2215
      break;
2603
2216
 
2604
2217
    case HA_ADMIN_FAILED:
2605
 
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
2606
 
      protocol->store(STRING_WITH_LEN("Operation failed"),
2607
 
                      system_charset_info);
 
2218
      session->client->store(STRING_WITH_LEN("status"));
 
2219
      session->client->store(STRING_WITH_LEN("Operation failed"));
2608
2220
      break;
2609
2221
 
2610
2222
    case HA_ADMIN_REJECT:
2611
 
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
2612
 
      protocol->store(STRING_WITH_LEN("Operation need committed state"),
2613
 
                      system_charset_info);
 
2223
      session->client->store(STRING_WITH_LEN("status"));
 
2224
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
2614
2225
      open_for_modify= false;
2615
2226
      break;
2616
2227
 
2617
2228
    case HA_ADMIN_ALREADY_DONE:
2618
 
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
2619
 
      protocol->store(STRING_WITH_LEN("Table is already up to date"),
2620
 
                      system_charset_info);
 
2229
      session->client->store(STRING_WITH_LEN("status"));
 
2230
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
2621
2231
      break;
2622
2232
 
2623
2233
    case HA_ADMIN_CORRUPT:
2624
 
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2625
 
      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
 
2234
      session->client->store(STRING_WITH_LEN("error"));
 
2235
      session->client->store(STRING_WITH_LEN("Corrupt"));
2626
2236
      fatal_error=1;
2627
2237
      break;
2628
2238
 
2629
2239
    case HA_ADMIN_INVALID:
2630
 
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2631
 
      protocol->store(STRING_WITH_LEN("Invalid argument"),
2632
 
                      system_charset_info);
 
2240
      session->client->store(STRING_WITH_LEN("error"));
 
2241
      session->client->store(STRING_WITH_LEN("Invalid argument"));
2633
2242
      break;
2634
2243
 
2635
2244
    case HA_ADMIN_TRY_ALTER:
2636
2245
    {
2637
2246
      /*
2638
2247
        This is currently used only by InnoDB. ha_innobase::optimize() answers
2639
 
        "try with alter", so here we close the table, do an ALTER TABLE,
 
2248
        "try with alter", so here we close the table, do an ALTER Table,
2640
2249
        reopen the table and do ha_innobase::analyze() on it.
2641
2250
      */
2642
 
      ha_autocommit_or_rollback(thd, 0);
2643
 
      close_thread_tables(thd);
2644
 
      TABLE_LIST *save_next_local= table->next_local,
 
2251
      ha_autocommit_or_rollback(session, 0);
 
2252
      session->close_thread_tables();
 
2253
      TableList *save_next_local= table->next_local,
2645
2254
                 *save_next_global= table->next_global;
2646
2255
      table->next_local= table->next_global= 0;
2647
 
      tmp_disable_binlog(thd); // binlogging is done by caller if wanted
2648
 
      result_code= mysql_recreate_table(thd, table);
2649
 
      reenable_binlog(thd);
 
2256
      result_code= mysql_recreate_table(session, table);
2650
2257
      /*
2651
2258
        mysql_recreate_table() can push OK or ERROR.
2652
2259
        Clear 'OK' status. If there is an error, keep it:
2653
 
        we will store the error message in a result set row 
 
2260
        we will store the error message in a result set row
2654
2261
        and then clear.
2655
2262
      */
2656
 
      if (thd->main_da.is_ok())
2657
 
        thd->main_da.reset_diagnostics_area();
2658
 
      ha_autocommit_or_rollback(thd, 0);
2659
 
      close_thread_tables(thd);
 
2263
      if (session->main_da.is_ok())
 
2264
        session->main_da.reset_diagnostics_area();
 
2265
      ha_autocommit_or_rollback(session, 0);
 
2266
      session->close_thread_tables();
2660
2267
      if (!result_code) // recreation went ok
2661
2268
      {
2662
 
        if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
2663
 
            ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
 
2269
        if ((table->table= session->openTableLock(table, lock_type)) &&
 
2270
            ((result_code= table->table->cursor->ha_analyze(session, check_opt)) > 0))
2664
2271
          result_code= 0; // analyze went ok
2665
2272
      }
2666
2273
      if (result_code) // either mysql_recreate_table or analyze failed
2667
2274
      {
2668
 
        assert(thd->is_error());
2669
 
        if (thd->is_error())
 
2275
        assert(session->is_error());
 
2276
        if (session->is_error())
2670
2277
        {
2671
 
          const char *err_msg= thd->main_da.message();
2672
 
          if (!thd->vio_ok())
2673
 
          {
2674
 
            sql_print_error(err_msg);
2675
 
          }
2676
 
          else
2677
 
          {
2678
 
            /* Hijack the row already in-progress. */
2679
 
            protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2680
 
            protocol->store(err_msg, system_charset_info);
2681
 
            (void)protocol->write();
2682
 
            /* Start off another row for HA_ADMIN_FAILED */
2683
 
            protocol->prepare_for_resend();
2684
 
            protocol->store(table_name, system_charset_info);
2685
 
            protocol->store(operator_name, system_charset_info);
2686
 
          }
2687
 
          thd->clear_error();
 
2278
          const char *err_msg= session->main_da.message();
 
2279
          /* Hijack the row already in-progress. */
 
2280
          session->client->store(STRING_WITH_LEN("error"));
 
2281
          session->client->store(err_msg);
 
2282
          (void)session->client->flush();
 
2283
          /* Start off another row for HA_ADMIN_FAILED */
 
2284
          session->client->store(table_name);
 
2285
          session->client->store(operator_name);
 
2286
          session->clear_error();
2688
2287
        }
2689
2288
      }
2690
2289
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
2692
2291
      table->next_global= save_next_global;
2693
2292
      goto send_result_message;
2694
2293
    }
2695
 
    case HA_ADMIN_WRONG_CHECKSUM:
2696
 
    {
2697
 
      protocol->store(STRING_WITH_LEN("note"), system_charset_info);
2698
 
      protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
2699
 
                      system_charset_info);
2700
 
      break;
2701
 
    }
2702
 
 
2703
2294
    case HA_ADMIN_NEEDS_UPGRADE:
2704
2295
    case HA_ADMIN_NEEDS_ALTER:
2705
2296
    {
2706
2297
      char buf[ERRMSGSIZE];
2707
 
      uint length;
 
2298
      uint32_t length;
2708
2299
 
2709
 
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
 
2300
      session->client->store(STRING_WITH_LEN("error"));
2710
2301
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
2711
 
      protocol->store(buf, length, system_charset_info);
 
2302
      session->client->store(buf, length);
2712
2303
      fatal_error=1;
2713
2304
      break;
2714
2305
    }
2716
2307
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
2717
2308
      {
2718
2309
        char buf[ERRMSGSIZE+20];
2719
 
        uint length=snprintf(buf, ERRMSGSIZE,
2720
 
                             "Unknown - internal error %d during operation",
 
2310
        uint32_t length=snprintf(buf, ERRMSGSIZE,
 
2311
                             _("Unknown - internal error %d during operation"),
2721
2312
                             result_code);
2722
 
        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2723
 
        protocol->store(buf, length, system_charset_info);
 
2313
        session->client->store(STRING_WITH_LEN("error"));
 
2314
        session->client->store(buf, length);
2724
2315
        fatal_error=1;
2725
2316
        break;
2726
2317
      }
2732
2323
      else if (open_for_modify)
2733
2324
      {
2734
2325
        if (table->table->s->tmp_table)
2735
 
          table->table->file->info(HA_STATUS_CONST);
 
2326
          table->table->cursor->info(HA_STATUS_CONST);
2736
2327
        else
2737
2328
        {
2738
2329
          pthread_mutex_lock(&LOCK_open);
2739
 
          remove_table_from_cache(thd, table->table->s->db.str,
 
2330
          remove_table_from_cache(session, table->table->s->db.str,
2740
2331
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
2741
2332
          pthread_mutex_unlock(&LOCK_open);
2742
2333
        }
2743
2334
      }
2744
2335
    }
2745
 
    ha_autocommit_or_rollback(thd, 0);
2746
 
    end_trans(thd, COMMIT);
2747
 
    close_thread_tables(thd);
 
2336
    ha_autocommit_or_rollback(session, 0);
 
2337
    session->endTransaction(COMMIT);
 
2338
    session->close_thread_tables();
2748
2339
    table->table=0;                             // For query cache
2749
 
    if (protocol->write())
 
2340
    if (session->client->flush())
2750
2341
      goto err;
2751
2342
  }
2752
2343
 
2753
 
  my_eof(thd);
 
2344
  session->my_eof();
2754
2345
  return(false);
2755
2346
 
2756
2347
err:
2757
 
  ha_autocommit_or_rollback(thd, 1);
2758
 
  end_trans(thd, ROLLBACK);
2759
 
  close_thread_tables(thd);                     // Shouldn't be needed
 
2348
  ha_autocommit_or_rollback(session, 1);
 
2349
  session->endTransaction(ROLLBACK);
 
2350
  session->close_thread_tables();                       // Shouldn't be needed
2760
2351
  if (table)
2761
2352
    table->table=0;
2762
2353
  return(true);
2763
2354
}
2764
2355
 
2765
 
 
2766
 
bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
2767
 
{
2768
 
  return(mysql_admin_table(thd, tables, check_opt,
2769
 
                                "repair", TL_WRITE, 1,
2770
 
                                test(check_opt->sql_flags & TT_USEFRM),
2771
 
                                HA_OPEN_FOR_REPAIR,
2772
 
                                &prepare_for_repair,
2773
 
                                &handler::ha_repair));
2774
 
}
2775
 
 
2776
 
 
2777
 
bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
2778
 
{
2779
 
  return(mysql_admin_table(thd, tables, check_opt,
2780
 
                                "optimize", TL_WRITE, 1,0,0,0,
2781
 
                                &handler::ha_optimize));
2782
 
}
2783
 
 
2784
 
 
2785
 
/*
2786
 
  Assigned specified indexes for a table into key cache
2787
 
 
2788
 
  SYNOPSIS
2789
 
    mysql_assign_to_keycache()
2790
 
    thd         Thread object
2791
 
    tables      Table list (one table only)
2792
 
 
2793
 
  RETURN VALUES
2794
 
   false ok
2795
 
   true  error
2796
 
*/
2797
 
 
2798
 
bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
2799
 
                             LEX_STRING *key_cache_name)
2800
 
{
2801
 
  HA_CHECK_OPT check_opt;
2802
 
  KEY_CACHE *key_cache;
2803
 
 
2804
 
  check_opt.init();
2805
 
  pthread_mutex_lock(&LOCK_global_system_variables);
2806
 
  if (!(key_cache= get_key_cache(key_cache_name)))
2807
 
  {
2808
 
    pthread_mutex_unlock(&LOCK_global_system_variables);
2809
 
    my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
2810
 
    return(true);
2811
 
  }
2812
 
  pthread_mutex_unlock(&LOCK_global_system_variables);
2813
 
  check_opt.key_cache= key_cache;
2814
 
  return(mysql_admin_table(thd, tables, &check_opt,
2815
 
                                "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
2816
 
                                0, 0, &handler::assign_to_keycache));
2817
 
}
2818
 
 
2819
 
 
2820
 
/*
2821
 
  Reassign all tables assigned to a key cache to another key cache
2822
 
 
2823
 
  SYNOPSIS
2824
 
    reassign_keycache_tables()
2825
 
    thd         Thread object
2826
 
    src_cache   Reference to the key cache to clean up
2827
 
    dest_cache  New key cache
2828
 
 
2829
 
  NOTES
2830
 
    This is called when one sets a key cache size to zero, in which
2831
 
    case we have to move the tables associated to this key cache to
2832
 
    the "default" one.
2833
 
 
2834
 
    One has to ensure that one never calls this function while
2835
 
    some other thread is changing the key cache. This is assured by
2836
 
    the caller setting src_cache->in_init before calling this function.
2837
 
 
2838
 
    We don't delete the old key cache as there may still be pointers pointing
2839
 
    to it for a while after this function returns.
2840
 
 
2841
 
 RETURN VALUES
2842
 
    0     ok
2843
 
*/
2844
 
 
2845
 
int reassign_keycache_tables(THD *thd __attribute__((unused)),
2846
 
                             KEY_CACHE *src_cache,
2847
 
                             KEY_CACHE *dst_cache)
2848
 
{
2849
 
  assert(src_cache != dst_cache);
2850
 
  assert(src_cache->in_init);
2851
 
  src_cache->param_buff_size= 0;                // Free key cache
2852
 
  ha_resize_key_cache(src_cache);
2853
 
  ha_change_key_cache(src_cache, dst_cache);
2854
 
  return(0);
2855
 
}
2856
 
 
2857
 
/**
2858
 
  @brief          Create frm file based on I_S table
2859
 
 
2860
 
  @param[in]      thd                      thread handler
2861
 
  @param[in]      schema_table             I_S table           
2862
 
  @param[in]      dst_path                 path where frm should be created
2863
 
  @param[in]      create_info              Create info
2864
 
 
2865
 
  @return         Operation status
2866
 
    @retval       0                        success
2867
 
    @retval       1                        error
2868
 
*/
2869
 
bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table,
2870
 
                                  char *dst_path, HA_CREATE_INFO *create_info)
2871
 
{
2872
 
  HA_CREATE_INFO local_create_info;
2873
 
  Alter_info alter_info;
2874
 
  bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
2875
 
  uint keys= schema_table->table->s->keys;
2876
 
  uint db_options= 0;
2877
 
 
2878
 
  memset(&local_create_info, 0, sizeof(local_create_info));
2879
 
  local_create_info.db_type= schema_table->table->s->db_type();
2880
 
  local_create_info.row_type= schema_table->table->s->row_type;
2881
 
  local_create_info.default_table_charset=default_charset_info;
2882
 
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
2883
 
  schema_table->table->use_all_columns();
2884
 
  if (mysql_prepare_alter_table(thd, schema_table->table,
2885
 
                                &local_create_info, &alter_info))
2886
 
    return(1);
2887
 
  if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
2888
 
                                 tmp_table, &db_options,
2889
 
                                 schema_table->table->file,
2890
 
                                 &schema_table->table->s->key_info, &keys, 0))
2891
 
    return(1);
2892
 
  local_create_info.max_rows= 0;
2893
 
  if (mysql_create_frm(thd, dst_path, NullS, NullS,
2894
 
                       &local_create_info, alter_info.create_list,
2895
 
                       keys, schema_table->table->s->key_info,
2896
 
                       schema_table->table->file))
2897
 
    return(1);
2898
 
  return(0);
2899
 
}
2900
 
 
 
2356
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2357
{
 
2358
  return(mysql_admin_table(session, tables, check_opt,
 
2359
                           "optimize", TL_WRITE, 1,0,0,0,
 
2360
                           &Cursor::ha_optimize));
 
2361
}
2901
2362
 
2902
2363
/*
2903
2364
  Create a table identical to the specified table
2904
2365
 
2905
2366
  SYNOPSIS
2906
2367
    mysql_create_like_table()
2907
 
    thd         Thread object
 
2368
    session             Thread object
2908
2369
    table       Table list element for target table
2909
2370
    src_table   Table list element for source table
2910
2371
    create_info Create info
2914
2375
    true  error
2915
2376
*/
2916
2377
 
2917
 
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
 
2378
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2379
                             drizzled::message::Table& create_table_proto,
2918
2380
                             HA_CREATE_INFO *create_info)
2919
2381
{
2920
 
  TABLE *name_lock= 0;
 
2382
  Table *name_lock= 0;
2921
2383
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2922
 
  uint dst_path_length;
 
2384
  uint32_t dst_path_length;
2923
2385
  char *db= table->db;
2924
2386
  char *table_name= table->table_name;
2925
2387
  int  err;
2926
2388
  bool res= true;
2927
 
  uint not_used;
2928
 
 
2929
 
 
2930
 
  /* CREATE TABLE ... LIKE is not allowed for views. */
2931
 
  src_table->required_type= FRMTYPE_TABLE;
 
2389
  uint32_t not_used;
 
2390
  message::Table src_proto;
2932
2391
 
2933
2392
  /*
2934
2393
    By opening source table we guarantee that it exists and no concurrent
2935
2394
    DDL operation will mess with it. Later we also take an exclusive
2936
 
    name-lock on target table name, which makes copying of .frm file,
2937
 
    call to ha_create_table() and binlogging atomic against concurrent DML
2938
 
    and DDL operations on target table. Thus by holding both these "locks"
2939
 
    we ensure that our statement is properly isolated from all concurrent
2940
 
    operations which matter.
 
2395
    name-lock on target table name, which makes copying of .frm cursor,
 
2396
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2397
    against concurrent DML and DDL operations on target table.
 
2398
    Thus by holding both these "locks" we ensure that our statement is
 
2399
    properly isolated from all concurrent operations which matter.
2941
2400
  */
2942
 
  if (open_tables(thd, &src_table, &not_used, 0))
2943
 
    return(true);
2944
 
 
2945
 
  strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
2946
 
 
2947
 
  /* 
 
2401
  if (session->open_tables_from_list(&src_table, &not_used))
 
2402
    return true;
 
2403
 
 
2404
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
 
2405
 
 
2406
 
 
2407
  /*
2948
2408
    Check that destination tables does not exist. Note that its name
2949
2409
    was already checked when it was added to the table list.
2950
2410
  */
2951
2411
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2952
2412
  {
2953
 
    if (find_temporary_table(thd, db, table_name))
 
2413
    if (session->find_temporary_table(db, table_name))
2954
2414
      goto table_exists;
2955
 
    dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
2956
 
    create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
 
2415
    dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2957
2416
  }
2958
2417
  else
2959
2418
  {
2960
 
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
2419
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2961
2420
      goto err;
2962
2421
    if (!name_lock)
2963
2422
      goto table_exists;
2964
2423
    dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2965
 
                                          db, table_name, reg_ext, 0);
2966
 
    if (!access(dst_path, F_OK))
 
2424
                                          db, table_name, false);
 
2425
    if (plugin::StorageEngine::getTableDefinition(*session, dst_path, db, table_name, false) == EEXIST)
2967
2426
      goto table_exists;
2968
2427
  }
2969
2428
 
2972
2431
 
2973
2432
    Altough exclusive name-lock on target table protects us from concurrent
2974
2433
    DML and DDL operations on it we still want to wrap .FRM creation and call
2975
 
    to ha_create_table() in critical section protected by LOCK_open in order
2976
 
    to provide minimal atomicity against operations which disregard name-locks,
2977
 
    like I_S implementation, for example. This is a temporary and should not
2978
 
    be copied. Instead we should fix our code to always honor name-locks.
 
2434
    to plugin::StorageEngine::createTable() in critical section protected by
 
2435
    LOCK_open in order to provide minimal atomicity against operations which
 
2436
    disregard name-locks, like I_S implementation, for example. This is a
 
2437
    temporary and should not be copied. Instead we should fix our code to
 
2438
    always honor name-locks.
2979
2439
 
2980
2440
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2981
 
    during the call to ha_create_table(). See bug #28614 for more info.
 
2441
    during the call to plugin::StorageEngine::createTable().
 
2442
    See bug #28614 for more info.
2982
2443
  */
2983
 
  VOID(pthread_mutex_lock(&LOCK_open));
2984
 
  if (src_table->schema_table)
 
2444
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2985
2445
  {
2986
 
    if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
 
2446
    int protoerr= EEXIST;
 
2447
 
 
2448
    if (src_table->schema_table)
2987
2449
    {
2988
 
      VOID(pthread_mutex_unlock(&LOCK_open));
2989
 
      goto err;
 
2450
      if (create_like_schema_frm(session, src_table, create_info, &src_proto))
 
2451
      {
 
2452
        pthread_mutex_unlock(&LOCK_open);
 
2453
        goto err;
 
2454
      }
2990
2455
    }
2991
 
  }
2992
 
  else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
2993
 
  {
2994
 
    if (my_errno == ENOENT)
2995
 
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
2996
2456
    else
2997
 
      my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2998
 
    VOID(pthread_mutex_unlock(&LOCK_open));
2999
 
    goto err;
 
2457
    {
 
2458
      protoerr= plugin::StorageEngine::getTableDefinition(*session,
 
2459
                                                          src_path,
 
2460
                                                          db,
 
2461
                                                          table_name,
 
2462
                                                          false,
 
2463
                                                          &src_proto);
 
2464
    }
 
2465
 
 
2466
    message::Table new_proto(src_proto);
 
2467
 
 
2468
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
 
2469
    {
 
2470
      message::Table::StorageEngine *protoengine;
 
2471
 
 
2472
      protoengine= new_proto.mutable_engine();
 
2473
      protoengine->set_name(create_table_proto.engine().name());
 
2474
    }
 
2475
 
 
2476
    string dst_proto_path(dst_path);
 
2477
    string file_ext = ".dfe";
 
2478
 
 
2479
    dst_proto_path.append(file_ext);
 
2480
 
 
2481
    if (protoerr == EEXIST)
 
2482
    {
 
2483
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
 
2484
                                                                       new_proto.engine().name());
 
2485
 
 
2486
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2487
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
 
2488
      else
 
2489
        protoerr= 0;
 
2490
    }
 
2491
 
 
2492
    if (protoerr)
 
2493
    {
 
2494
      if (my_errno == ENOENT)
 
2495
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2496
      else
 
2497
        my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
 
2498
      pthread_mutex_unlock(&LOCK_open);
 
2499
      goto err;
 
2500
    }
 
2501
 
 
2502
    /*
 
2503
      As mysql_truncate don't work on a new table at this stage of
 
2504
      creation, instead create the table directly (for both normal
 
2505
      and temporary tables).
 
2506
    */
 
2507
    err= plugin::StorageEngine::createTable(*session, dst_path, db, table_name, *create_info, 
 
2508
                                            true, new_proto);
3000
2509
  }
3001
 
 
3002
 
  /*
3003
 
    As mysql_truncate don't work on a new table at this stage of
3004
 
    creation, instead create the table directly (for both normal
3005
 
    and temporary tables).
3006
 
  */
3007
 
  dst_path[dst_path_length - reg_ext_length]= '\0';  // Remove .frm
3008
 
  if (thd->variables.keep_files_on_create)
3009
 
    create_info->options|= HA_CREATE_KEEP_FILES;
3010
 
  err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3011
 
  VOID(pthread_mutex_unlock(&LOCK_open));
 
2510
  pthread_mutex_unlock(&LOCK_open);
3012
2511
 
3013
2512
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3014
2513
  {
3015
 
    if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3016
 
                                     OTM_OPEN))
 
2514
    if (err || !session->open_temporary_table(dst_path, db, table_name, true))
3017
2515
    {
3018
 
      (void) rm_temporary_table(create_info->db_type,
3019
 
                                dst_path, false); /* purecov: inspected */
3020
 
      goto err;     /* purecov: inspected */
 
2516
      (void) session->rm_temporary_table(create_info->db_type, dst_path);
 
2517
      goto err;
3021
2518
    }
3022
2519
  }
3023
2520
  else if (err)
3024
2521
  {
3025
 
    (void) quick_rm_table(create_info->db_type, db,
3026
 
                          table_name, 0); /* purecov: inspected */
3027
 
    goto err;       /* purecov: inspected */
 
2522
    (void) quick_rm_table(*session, db,
 
2523
                          table_name, false);
 
2524
    goto err;
3028
2525
  }
3029
2526
 
3030
2527
  /*
3031
2528
    We have to write the query before we unlock the tables.
3032
2529
  */
3033
 
  if (thd->current_stmt_binlog_row_based)
3034
2530
  {
3035
2531
    /*
3036
2532
       Since temporary tables are not replicated under row-based
3063
2559
          of this function.
3064
2560
        */
3065
2561
        table->table= name_lock;
3066
 
        VOID(pthread_mutex_lock(&LOCK_open));
3067
 
        if (reopen_name_locked_table(thd, table, false))
 
2562
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2563
        if (session->reopen_name_locked_table(table, false))
3068
2564
        {
3069
 
          VOID(pthread_mutex_unlock(&LOCK_open));
 
2565
          pthread_mutex_unlock(&LOCK_open);
3070
2566
          goto err;
3071
2567
        }
3072
 
        VOID(pthread_mutex_unlock(&LOCK_open));
 
2568
        pthread_mutex_unlock(&LOCK_open);
3073
2569
 
3074
 
        int result= store_create_info(thd, table, &query,
3075
 
                                               create_info);
 
2570
        int result= store_create_info(table, &query, create_info);
3076
2571
 
3077
2572
        assert(result == 0); // store_create_info() always return 0
3078
 
        write_bin_log(thd, true, query.ptr(), query.length());
 
2573
        write_bin_log(session, query.ptr(), query.length());
3079
2574
      }
3080
2575
      else                                      // Case 1
3081
 
        write_bin_log(thd, true, thd->query, thd->query_length);
 
2576
        write_bin_log(session, session->query, session->query_length);
3082
2577
    }
3083
 
    /*
3084
 
      Case 3 and 4 does nothing under RBR
3085
 
    */
3086
2578
  }
3087
 
  else
3088
 
    write_bin_log(thd, true, thd->query, thd->query_length);
3089
2579
 
3090
2580
  res= false;
3091
2581
  goto err;
3096
2586
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
3097
2587
    snprintf(warn_buff, sizeof(warn_buff),
3098
2588
             ER(ER_TABLE_EXISTS_ERROR), table_name);
3099
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2589
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3100
2590
                 ER_TABLE_EXISTS_ERROR,warn_buff);
3101
2591
    res= false;
3102
2592
  }
3106
2596
err:
3107
2597
  if (name_lock)
3108
2598
  {
3109
 
    pthread_mutex_lock(&LOCK_open);
3110
 
    unlink_open_table(thd, name_lock, false);
 
2599
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2600
    session->unlink_open_table(name_lock);
3111
2601
    pthread_mutex_unlock(&LOCK_open);
3112
2602
  }
3113
2603
  return(res);
3114
2604
}
3115
2605
 
3116
2606
 
3117
 
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
2607
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
3118
2608
{
3119
2609
  thr_lock_type lock_type = TL_READ_NO_INSERT;
3120
2610
 
3121
 
  return(mysql_admin_table(thd, tables, check_opt,
 
2611
  return(mysql_admin_table(session, tables, check_opt,
3122
2612
                                "analyze", lock_type, 1, 0, 0, 0,
3123
 
                                &handler::ha_analyze));
 
2613
                                &Cursor::ha_analyze));
3124
2614
}
3125
2615
 
3126
2616
 
3127
 
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
 
2617
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
3128
2618
{
3129
2619
  thr_lock_type lock_type = TL_READ_NO_INSERT;
3130
2620
 
3131
 
  return(mysql_admin_table(thd, tables, check_opt,
 
2621
  return(mysql_admin_table(session, tables, check_opt,
3132
2622
                                "check", lock_type,
3133
2623
                                0, 0, HA_OPEN_FOR_REPAIR, 0,
3134
 
                                &handler::ha_check));
3135
 
}
3136
 
 
3137
 
 
3138
 
/* table_list should contain just one table */
3139
 
static int
3140
 
mysql_discard_or_import_tablespace(THD *thd,
3141
 
                                   TABLE_LIST *table_list,
3142
 
                                   enum tablespace_op_type tablespace_op)
3143
 
{
3144
 
  TABLE *table;
3145
 
  bool discard;
3146
 
  int error;
3147
 
 
3148
 
  /*
3149
 
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
3150
 
    ALTER TABLE
3151
 
  */
3152
 
 
3153
 
  thd_proc_info(thd, "discard_or_import_tablespace");
3154
 
 
3155
 
  discard= test(tablespace_op == DISCARD_TABLESPACE);
3156
 
 
3157
 
 /*
3158
 
   We set this flag so that ha_innobase::open and ::external_lock() do
3159
 
   not complain when we lock the table
3160
 
 */
3161
 
  thd->tablespace_op= true;
3162
 
  if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3163
 
  {
3164
 
    thd->tablespace_op=false;
3165
 
    return(-1);
3166
 
  }
3167
 
 
3168
 
  error= table->file->ha_discard_or_import_tablespace(discard);
3169
 
 
3170
 
  thd_proc_info(thd, "end");
3171
 
 
3172
 
  if (error)
3173
 
    goto err;
3174
 
 
3175
 
  /* The ALTER TABLE is always in its own transaction */
3176
 
  error = ha_autocommit_or_rollback(thd, 0);
3177
 
  if (end_active_trans(thd))
3178
 
    error=1;
3179
 
  if (error)
3180
 
    goto err;
3181
 
  write_bin_log(thd, false, thd->query, thd->query_length);
3182
 
 
3183
 
err:
3184
 
  ha_autocommit_or_rollback(thd, error);
3185
 
  thd->tablespace_op=false;
3186
 
  
3187
 
  if (error == 0)
3188
 
  {
3189
 
    my_ok(thd);
3190
 
    return(0);
3191
 
  }
3192
 
 
3193
 
  table->file->print_error(error, MYF(0));
3194
 
    
3195
 
  return(-1);
3196
 
}
3197
 
 
3198
 
/**
3199
 
  Copy all changes detected by parser to the HA_ALTER_FLAGS
3200
 
*/
3201
 
 
3202
 
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
3203
 
{
3204
 
  uint flags= alter_info->flags;
3205
 
 
3206
 
  if (ALTER_ADD_COLUMN & flags)
3207
 
    *alter_flags|= HA_ADD_COLUMN;
3208
 
  if (ALTER_DROP_COLUMN & flags)
3209
 
    *alter_flags|= HA_DROP_COLUMN;
3210
 
  if (ALTER_RENAME & flags)
3211
 
    *alter_flags|= HA_RENAME_TABLE;
3212
 
  if (ALTER_CHANGE_COLUMN & flags)
3213
 
    *alter_flags|= HA_CHANGE_COLUMN;
3214
 
  if (ALTER_COLUMN_DEFAULT & flags)
3215
 
    *alter_flags|= HA_COLUMN_DEFAULT_VALUE;
3216
 
  if (ALTER_COLUMN_STORAGE & flags)
3217
 
    *alter_flags|= HA_COLUMN_STORAGE;
3218
 
  if (ALTER_COLUMN_FORMAT & flags)
3219
 
    *alter_flags|= HA_COLUMN_FORMAT;
3220
 
  if (ALTER_COLUMN_ORDER & flags)
3221
 
    *alter_flags|= HA_ALTER_COLUMN_ORDER;
3222
 
  if (ALTER_STORAGE & flags)
3223
 
    *alter_flags|= HA_ALTER_STORAGE;
3224
 
  if (ALTER_ROW_FORMAT & flags)
3225
 
    *alter_flags|= HA_ALTER_ROW_FORMAT;
3226
 
  if (ALTER_RECREATE & flags)
3227
 
    *alter_flags|= HA_RECREATE;
3228
 
  if (ALTER_FOREIGN_KEY & flags)
3229
 
    *alter_flags|= HA_ALTER_FOREIGN_KEY;
3230
 
}
3231
 
 
3232
 
 
3233
 
/**
3234
 
   @param       thd                Thread
3235
 
   @param       table              The original table.
3236
 
   @param       alter_info         Alter options, fields and keys for the new
3237
 
                                   table.
3238
 
   @param       create_info        Create options for the new table.
3239
 
   @param       order_num          Number of order list elements.
3240
 
   @param[out]  ha_alter_flags  Flags that indicate what will be changed
3241
 
   @param[out]  ha_alter_info      Data structures needed for on-line alter
3242
 
   @param[out]  table_changes      Information about particular change
3243
 
 
3244
 
   First argument 'table' contains information of the original
3245
 
   table, which includes all corresponding parts that the new
3246
 
   table has in arguments create_list, key_list and create_info.
3247
 
 
3248
 
   By comparing the changes between the original and new table
3249
 
   we can determine how much it has changed after ALTER TABLE
3250
 
   and whether we need to make a copy of the table, or just change
3251
 
   the .frm file.
3252
 
 
3253
 
   Mark any changes detected in the ha_alter_flags.
3254
 
 
3255
 
   If there are no data changes, but index changes, 'index_drop_buffer'
3256
 
   and/or 'index_add_buffer' are populated with offsets into
3257
 
   table->key_info or key_info_buffer respectively for the indexes
3258
 
   that need to be dropped and/or (re-)created.
3259
 
 
3260
 
   @retval true  error
3261
 
   @retval false success
3262
 
*/
3263
 
 
3264
 
static
3265
 
bool
3266
 
compare_tables(THD *thd,
3267
 
               TABLE *table,
3268
 
               Alter_info *alter_info,
3269
 
                           HA_CREATE_INFO *create_info,
3270
 
               uint order_num,
3271
 
               HA_ALTER_FLAGS *alter_flags,
3272
 
               HA_ALTER_INFO *ha_alter_info,
3273
 
               uint *table_changes)
3274
 
{
3275
 
  Field **f_ptr, *field;
3276
 
  uint table_changes_local= 0;
3277
 
  List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
3278
 
  Create_field *new_field;
3279
 
  KEY_PART_INFO *key_part;
3280
 
  KEY_PART_INFO *end;
3281
 
  /*
3282
 
    Remember if the new definition has new VARCHAR column;
3283
 
    create_info->varchar will be reset in mysql_prepare_create_table.
3284
 
  */
3285
 
  bool varchar= create_info->varchar;
3286
 
 
3287
 
  {
3288
 
    /*
3289
 
      Create a copy of alter_info.
3290
 
      To compare the new and old table definitions, we need to "prepare"
3291
 
      the new definition - transform it from parser output to a format
3292
 
      that describes the final table layout (all column defaults are
3293
 
      initialized, duplicate columns are removed). This is done by
3294
 
      mysql_prepare_create_table.  Unfortunately,
3295
 
      mysql_prepare_create_table performs its transformations
3296
 
      "in-place", that is, modifies the argument.  Since we would
3297
 
      like to keep compare_tables() idempotent (not altering any
3298
 
      of the arguments) we create a copy of alter_info here and
3299
 
      pass it to mysql_prepare_create_table, then use the result
3300
 
      to evaluate possibility of fast ALTER TABLE, and then
3301
 
      destroy the copy.
3302
 
    */
3303
 
    Alter_info tmp_alter_info(*alter_info, thd->mem_root);
3304
 
    THD *thd= table->in_use;
3305
 
    uint db_options= 0; /* not used */
3306
 
    /* Create the prepared information. */
3307
 
    if (mysql_prepare_create_table(thd, create_info,
3308
 
                                   &tmp_alter_info,
3309
 
                                   (table->s->tmp_table != NO_TMP_TABLE),
3310
 
                                   &db_options,
3311
 
                                   table->file,
3312
 
                                   &ha_alter_info->key_info_buffer,
3313
 
                                   &ha_alter_info->key_count,
3314
 
                                   /* select_field_count */ 0))
3315
 
      return(true);
3316
 
    /* Allocate result buffers. */
3317
 
    if (! (ha_alter_info->index_drop_buffer=
3318
 
           (uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
3319
 
        ! (ha_alter_info->index_add_buffer=
3320
 
           (uint*) thd->alloc(sizeof(uint) *
3321
 
                              tmp_alter_info.key_list.elements)))
3322
 
      return(true);
3323
 
  }
3324
 
  /*
3325
 
    First we setup ha_alter_flags based on what was detected
3326
 
    by parser
3327
 
  */
3328
 
  setup_ha_alter_flags(alter_info, alter_flags);
3329
 
 
3330
 
 
3331
 
  /*
3332
 
    Some very basic checks. If number of fields changes, or the
3333
 
    handler, we need to run full ALTER TABLE. In the future
3334
 
    new fields can be added and old dropped without copy, but
3335
 
    not yet.
3336
 
 
3337
 
    Test also that engine was not given during ALTER TABLE, or
3338
 
    we are force to run regular alter table (copy).
3339
 
    E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
3340
 
 
3341
 
    For the following ones we also want to run regular alter table:
3342
 
    ALTER TABLE tbl_name ORDER BY ..
3343
 
    ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
3344
 
 
3345
 
    At the moment we can't handle altering temporary tables without a copy.
3346
 
    We also test if OPTIMIZE TABLE was given and was mapped to alter table.
3347
 
    In that case we always do full copy.
3348
 
 
3349
 
    There was a bug prior to mysql-4.0.25. Number of null fields was
3350
 
    calculated incorrectly. As a result frm and data files gets out of
3351
 
    sync after fast alter table. There is no way to determine by which
3352
 
    mysql version (in 4.0 and 4.1 branches) table was created, thus we
3353
 
    disable fast alter table for all tables created by mysql versions
3354
 
    prior to 5.0 branch.
3355
 
    See BUG#6236.
3356
 
  */
3357
 
  if (table->s->fields != alter_info->create_list.elements ||
3358
 
      table->s->db_type() != create_info->db_type ||
3359
 
      table->s->tmp_table ||
3360
 
      create_info->used_fields & HA_CREATE_USED_ENGINE ||
3361
 
      create_info->used_fields & HA_CREATE_USED_CHARSET ||
3362
 
      create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
3363
 
      create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
3364
 
      (alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
3365
 
      order_num ||
3366
 
      !table->s->mysql_version ||
3367
 
      (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3368
 
  {
3369
 
    *table_changes= IS_EQUAL_NO;
3370
 
    /*
3371
 
      Check what has changed and set alter_flags
3372
 
    */
3373
 
    if (table->s->fields < alter_info->create_list.elements)
3374
 
      *alter_flags|= HA_ADD_COLUMN;
3375
 
    else if (table->s->fields > alter_info->create_list.elements)
3376
 
      *alter_flags|= HA_DROP_COLUMN;
3377
 
    if (create_info->db_type != table->s->db_type() ||
3378
 
        create_info->used_fields & HA_CREATE_USED_ENGINE)
3379
 
      *alter_flags|= HA_ALTER_STORAGE_ENGINE;
3380
 
    if (create_info->used_fields & HA_CREATE_USED_CHARSET)
3381
 
      *alter_flags|= HA_CHANGE_CHARACTER_SET;
3382
 
    if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
3383
 
      *alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
3384
 
    if (alter_info->flags & ALTER_RECREATE)
3385
 
      *alter_flags|= HA_RECREATE;
3386
 
    /* TODO check for ADD/DROP FOREIGN KEY */
3387
 
    if (alter_info->flags & ALTER_FOREIGN_KEY)
3388
 
      *alter_flags|=  HA_ALTER_FOREIGN_KEY;
3389
 
    if (!table->s->mysql_version ||
3390
 
        (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3391
 
      *alter_flags|=  HA_ALTER_COLUMN_TYPE;
3392
 
  }
3393
 
  /*
3394
 
    Go through fields and check if the original ones are compatible
3395
 
    with new table.
3396
 
  */
3397
 
  for (f_ptr= table->field, new_field= new_field_it++;
3398
 
       (new_field && (field= *f_ptr));
3399
 
       f_ptr++, new_field= new_field_it++)
3400
 
  {
3401
 
    /* Make sure we have at least the default charset in use. */
3402
 
    if (!new_field->charset)
3403
 
      new_field->charset= create_info->default_table_charset;
3404
 
 
3405
 
    /* Don't pack rows in old tables if the user has requested this. */
3406
 
    if (create_info->row_type == ROW_TYPE_DYNAMIC ||
3407
 
        (new_field->flags & BLOB_FLAG) ||
3408
 
        (new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
3409
 
      create_info->table_options|= HA_OPTION_PACK_RECORD;
3410
 
 
3411
 
    /* Check how fields have been modified */
3412
 
    if (alter_info->flags & ALTER_CHANGE_COLUMN)
3413
 
    {
3414
 
      /* Evaluate changes bitmap and send to check_if_incompatible_data() */
3415
 
      if (!(table_changes_local= field->is_equal(new_field)))
3416
 
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
3417
 
 
3418
 
      /* Check if field was renamed */
3419
 
      field->flags&= ~FIELD_IS_RENAMED;
3420
 
      if (my_strcasecmp(system_charset_info,
3421
 
                        field->field_name,
3422
 
                        new_field->field_name))
3423
 
      {
3424
 
        field->flags|= FIELD_IS_RENAMED;
3425
 
        *alter_flags|= HA_ALTER_COLUMN_NAME;
3426
 
      }
3427
 
 
3428
 
      *table_changes&= table_changes_local;
3429
 
      if (table_changes_local == IS_EQUAL_PACK_LENGTH)
3430
 
        *alter_flags|= HA_ALTER_COLUMN_TYPE;
3431
 
 
3432
 
      /* Check that NULL behavior is same for old and new fields */
3433
 
      if ((new_field->flags & NOT_NULL_FLAG) !=
3434
 
          (uint) (field->flags & NOT_NULL_FLAG))
3435
 
      {
3436
 
        *table_changes= IS_EQUAL_NO;
3437
 
        *alter_flags|= HA_ALTER_COLUMN_NULLABLE;
3438
 
      }
3439
 
    }
3440
 
 
3441
 
    /* Clear indexed marker */
3442
 
    field->flags&= ~FIELD_IN_ADD_INDEX;
3443
 
  }
3444
 
 
3445
 
  /*
3446
 
    Go through keys and check if the original ones are compatible
3447
 
    with new table.
3448
 
  */
3449
 
  KEY *table_key;
3450
 
  KEY *table_key_end= table->key_info + table->s->keys;
3451
 
  KEY *new_key;
3452
 
  KEY *new_key_end=
3453
 
       ha_alter_info->key_info_buffer + ha_alter_info->key_count;
3454
 
 
3455
 
  /*
3456
 
    Step through all keys of the old table and search matching new keys.
3457
 
  */
3458
 
  ha_alter_info->index_drop_count= 0;
3459
 
  ha_alter_info->index_add_count= 0;
3460
 
  for (table_key= table->key_info; table_key < table_key_end; table_key++)
3461
 
  {
3462
 
    KEY_PART_INFO *table_part;
3463
 
    KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
3464
 
    KEY_PART_INFO *new_part;
3465
 
 
3466
 
    /* Search a new key with the same name. */
3467
 
    for (new_key= ha_alter_info->key_info_buffer;
3468
 
         new_key < new_key_end;
3469
 
         new_key++)
3470
 
    {
3471
 
      if (! strcmp(table_key->name, new_key->name))
3472
 
        break;
3473
 
    }
3474
 
    if (new_key >= new_key_end)
3475
 
    {
3476
 
      /* Key not found. Add the offset of the key to the drop buffer. */
3477
 
      ha_alter_info->index_drop_buffer
3478
 
           [ha_alter_info->index_drop_count++]=
3479
 
           table_key - table->key_info;
3480
 
      if (table_key->flags & HA_NOSAME)
3481
 
      {
3482
 
        /* Unique key. Check for "PRIMARY". */
3483
 
        if (! my_strcasecmp(system_charset_info,
3484
 
                            table_key->name, primary_key_name))
3485
 
          *alter_flags|= HA_DROP_PK_INDEX;
3486
 
        else
3487
 
          *alter_flags|= HA_DROP_UNIQUE_INDEX;
3488
 
      }
3489
 
      else
3490
 
        *alter_flags|= HA_DROP_INDEX;
3491
 
      *table_changes= IS_EQUAL_NO;
3492
 
      continue;
3493
 
    }
3494
 
 
3495
 
    /* Check that the key types are compatible between old and new tables. */
3496
 
    if ((table_key->algorithm != new_key->algorithm) ||
3497
 
        ((table_key->flags & HA_KEYFLAG_MASK) !=
3498
 
         (new_key->flags & HA_KEYFLAG_MASK)) ||
3499
 
        (table_key->key_parts != new_key->key_parts))
3500
 
    {
3501
 
      if (table_key->flags & HA_NOSAME)
3502
 
      {
3503
 
        // Unique key. Check for "PRIMARY".
3504
 
        if (! my_strcasecmp(system_charset_info,
3505
 
                            table_key->name, primary_key_name))
3506
 
          *alter_flags|= HA_ALTER_PK_INDEX;
3507
 
        else
3508
 
          *alter_flags|= HA_ALTER_UNIQUE_INDEX;
3509
 
      }
3510
 
      else
3511
 
        *alter_flags|= HA_ALTER_INDEX;
3512
 
      goto index_changed;
3513
 
    }
3514
 
 
3515
 
    /*
3516
 
      Check that the key parts remain compatible between the old and
3517
 
      new tables.
3518
 
    */
3519
 
    for (table_part= table_key->key_part, new_part= new_key->key_part;
3520
 
         table_part < table_part_end;
3521
 
         table_part++, new_part++)
3522
 
    {
3523
 
      /*
3524
 
        Key definition has changed if we are using a different field or
3525
 
        if the used key part length is different. We know that the fields
3526
 
        did not change. Comparing field numbers is sufficient.
3527
 
      */
3528
 
      if ((table_part->length != new_part->length) ||
3529
 
          (table_part->fieldnr - 1 != new_part->fieldnr))
3530
 
      {
3531
 
        if (table_key->flags & HA_NOSAME)
3532
 
        {
3533
 
          /* Unique key. Check for "PRIMARY" */
3534
 
          if (! my_strcasecmp(system_charset_info,
3535
 
                              table_key->name, primary_key_name))
3536
 
            *alter_flags|= HA_ALTER_PK_INDEX;
3537
 
          else
3538
 
            *alter_flags|= HA_ALTER_UNIQUE_INDEX;
3539
 
        }
3540
 
        else
3541
 
          *alter_flags|= HA_ALTER_INDEX;
3542
 
        goto index_changed;
3543
 
      }
3544
 
    }
3545
 
    continue;
3546
 
 
3547
 
  index_changed:
3548
 
    /* Key modified. Add the offset of the key to both buffers. */
3549
 
    ha_alter_info->index_drop_buffer
3550
 
         [ha_alter_info->index_drop_count++]=
3551
 
         table_key - table->key_info;
3552
 
    ha_alter_info->index_add_buffer
3553
 
         [ha_alter_info->index_add_count++]=
3554
 
         new_key - ha_alter_info->key_info_buffer;
3555
 
    key_part= new_key->key_part;
3556
 
    end= key_part + new_key->key_parts;
3557
 
    for(; key_part != end; key_part++)
3558
 
    {
3559
 
      /* Mark field to be part of new key */
3560
 
      if ((field= table->field[key_part->fieldnr]))
3561
 
        field->flags|= FIELD_IN_ADD_INDEX;
3562
 
    }
3563
 
    *table_changes= IS_EQUAL_NO;
3564
 
  }
3565
 
  /*end of for (; table_key < table_key_end;) */
3566
 
 
3567
 
  /*
3568
 
    Step through all keys of the new table and find matching old keys.
3569
 
  */
3570
 
  for (new_key= ha_alter_info->key_info_buffer;
3571
 
       new_key < new_key_end;
3572
 
       new_key++)
3573
 
  {
3574
 
    /* Search an old key with the same name. */
3575
 
    for (table_key= table->key_info; table_key < table_key_end; table_key++)
3576
 
    {
3577
 
      if (! strcmp(table_key->name, new_key->name))
3578
 
        break;
3579
 
    }
3580
 
    if (table_key >= table_key_end)
3581
 
    {
3582
 
      /* Key not found. Add the offset of the key to the add buffer. */
3583
 
      ha_alter_info->index_add_buffer
3584
 
           [ha_alter_info->index_add_count++]=
3585
 
           new_key - ha_alter_info->key_info_buffer;
3586
 
      key_part= new_key->key_part;
3587
 
      end= key_part + new_key->key_parts;
3588
 
      for(; key_part != end; key_part++)
3589
 
      {
3590
 
        /* Mark field to be part of new key */
3591
 
        if ((field= table->field[key_part->fieldnr]))
3592
 
          field->flags|= FIELD_IN_ADD_INDEX;
3593
 
      }
3594
 
      if (new_key->flags & HA_NOSAME)
3595
 
      {
3596
 
        /* Unique key. Check for "PRIMARY" */
3597
 
        if (! my_strcasecmp(system_charset_info,
3598
 
                            new_key->name, primary_key_name))
3599
 
          *alter_flags|= HA_ADD_PK_INDEX;
3600
 
        else
3601
 
        *alter_flags|= HA_ADD_UNIQUE_INDEX;
3602
 
      }
3603
 
      else
3604
 
        *alter_flags|= HA_ADD_INDEX;
3605
 
      *table_changes= IS_EQUAL_NO;
3606
 
    }
3607
 
  }
3608
 
 
3609
 
  return(false);
3610
 
}
3611
 
 
3612
 
 
3613
 
/*
3614
 
  Manages enabling/disabling of indexes for ALTER TABLE
3615
 
 
3616
 
  SYNOPSIS
3617
 
    alter_table_manage_keys()
3618
 
      table                  Target table
3619
 
      indexes_were_disabled  Whether the indexes of the from table
3620
 
                             were disabled
3621
 
      keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
3622
 
 
3623
 
  RETURN VALUES
3624
 
    false  OK
3625
 
    true   Error
3626
 
*/
3627
 
 
3628
 
static
3629
 
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
3630
 
                             enum enum_enable_or_disable keys_onoff)
3631
 
{
3632
 
  int error= 0;
3633
 
  switch (keys_onoff) {
3634
 
  case ENABLE:
3635
 
    error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3636
 
    break;
3637
 
  case LEAVE_AS_IS:
3638
 
    if (!indexes_were_disabled)
3639
 
      break;
3640
 
    /* fall-through: disabled indexes */
3641
 
  case DISABLE:
3642
 
    error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3643
 
  }
3644
 
 
3645
 
  if (error == HA_ERR_WRONG_COMMAND)
3646
 
  {
3647
 
    push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3648
 
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3649
 
                        table->s->table_name.str);
3650
 
    error= 0;
3651
 
  } else if (error)
3652
 
    table->file->print_error(error, MYF(0));
3653
 
 
3654
 
  return(error);
3655
 
}
3656
 
 
3657
 
int create_temporary_table(THD *thd,
3658
 
                           TABLE *table,
3659
 
                           char *new_db,
3660
 
                           char *tmp_name,
3661
 
                           HA_CREATE_INFO *create_info,
3662
 
                           Alter_info *alter_info,
3663
 
                           bool db_changed)
3664
 
{
3665
 
  int error;
3666
 
  char index_file[FN_REFLEN], data_file[FN_REFLEN];
3667
 
  handlerton *old_db_type, *new_db_type;
3668
 
  old_db_type= table->s->db_type();
3669
 
  new_db_type= create_info->db_type;
3670
 
  /*
3671
 
    Handling of symlinked tables:
3672
 
    If no rename:
3673
 
      Create new data file and index file on the same disk as the
3674
 
      old data and index files.
3675
 
      Copy data.
3676
 
      Rename new data file over old data file and new index file over
3677
 
      old index file.
3678
 
      Symlinks are not changed.
3679
 
 
3680
 
   If rename:
3681
 
      Create new data file and index file on the same disk as the
3682
 
      old data and index files.  Create also symlinks to point at
3683
 
      the new tables.
3684
 
      Copy data.
3685
 
      At end, rename intermediate tables, and symlinks to intermediate
3686
 
      table, to final table name.
3687
 
      Remove old table and old symlinks
3688
 
 
3689
 
    If rename is made to another database:
3690
 
      Create new tables in new database.
3691
 
      Copy data.
3692
 
      Remove old table and symlinks.
3693
 
  */
3694
 
  if (db_changed)               // Ignore symlink if db changed
3695
 
  {
3696
 
    if (create_info->index_file_name)
3697
 
    {
3698
 
      /* Fix index_file_name to have 'tmp_name' as basename */
3699
 
      stpcpy(index_file, tmp_name);
3700
 
      create_info->index_file_name=fn_same(index_file,
3701
 
                                           create_info->index_file_name,
3702
 
                                           1);
3703
 
    }
3704
 
    if (create_info->data_file_name)
3705
 
    {
3706
 
      /* Fix data_file_name to have 'tmp_name' as basename */
3707
 
      stpcpy(data_file, tmp_name);
3708
 
      create_info->data_file_name=fn_same(data_file,
3709
 
                                          create_info->data_file_name,
3710
 
                                          1);
3711
 
    }
3712
 
  }
3713
 
  else
3714
 
    create_info->data_file_name=create_info->index_file_name=0;
3715
 
 
3716
 
  /*
3717
 
    Create a table with a temporary name.
3718
 
    With create_info->frm_only == 1 this creates a .frm file only.
3719
 
    We don't log the statement, it will be logged later.
3720
 
  */
3721
 
  tmp_disable_binlog(thd);
3722
 
  error= mysql_create_table(thd, new_db, tmp_name,
3723
 
                            create_info, alter_info, 1, 0);
3724
 
  reenable_binlog(thd);
3725
 
 
3726
 
  return(error);
3727
 
}
3728
 
 
3729
 
/*
3730
 
  Create a temporary table that reflects what an alter table operation
3731
 
  will accomplish.
3732
 
 
3733
 
  SYNOPSIS
3734
 
    create_altered_table()
3735
 
      thd              Thread handle
3736
 
      table            The original table
3737
 
      create_info      Information from the parsing phase about new
3738
 
                       table properties.
3739
 
      alter_info       Lists of fields, keys to be changed, added
3740
 
                       or dropped.
3741
 
      db_change        Specifies if the table is moved to another database
3742
 
  RETURN
3743
 
    A temporary table with all changes
3744
 
    NULL if error
3745
 
  NOTES
3746
 
    The temporary table is created without storing it in any storage engine
3747
 
    and is opened only to get the table struct and frm file reference.
3748
 
*/
3749
 
TABLE *create_altered_table(THD *thd,
3750
 
                            TABLE *table,
3751
 
                            char *new_db,
3752
 
                            HA_CREATE_INFO *create_info,
3753
 
                            Alter_info *alter_info,
3754
 
                            bool db_change)
3755
 
{
3756
 
  int error;
3757
 
  HA_CREATE_INFO altered_create_info(*create_info);
3758
 
  TABLE *altered_table;
3759
 
  char tmp_name[80];
3760
 
  char path[FN_REFLEN];
3761
 
 
3762
 
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3763
 
           tmp_file_prefix, current_pid, thd->thread_id);
3764
 
  /* Safety fix for InnoDB */
3765
 
  if (lower_case_table_names)
3766
 
    my_casedn_str(files_charset_info, tmp_name);
3767
 
  altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3768
 
  altered_create_info.frm_only= 1;
3769
 
  if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3770
 
                                     &altered_create_info,
3771
 
                                     alter_info, db_change)))
3772
 
  {
3773
 
    return(NULL);
3774
 
  };
3775
 
 
3776
 
  build_table_filename(path, sizeof(path), new_db, tmp_name, "",
3777
 
                       FN_IS_TMP);
3778
 
  altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
3779
 
                                      OTM_ALTER);
3780
 
  return(altered_table);
3781
 
 
3782
 
  return(NULL);
3783
 
}
3784
 
 
3785
 
 
3786
 
/*
3787
 
  Perform a fast or on-line alter table
3788
 
 
3789
 
  SYNOPSIS
3790
 
    mysql_fast_or_online_alter_table()
3791
 
      thd              Thread handle
3792
 
      table            The original table
3793
 
      altered_table    A temporary table showing how we will change table
3794
 
      create_info      Information from the parsing phase about new
3795
 
                       table properties.
3796
 
      alter_info       Storage place for data used during different phases
3797
 
      ha_alter_flags   Bitmask that shows what will be changed
3798
 
      keys_onoff       Specifies if keys are to be enabled/disabled
3799
 
  RETURN
3800
 
     0  OK
3801
 
    >0  An error occured during the on-line alter table operation
3802
 
    -1  Error when re-opening table
3803
 
  NOTES
3804
 
    If mysql_alter_table does not need to copy the table, it is
3805
 
    either a fast alter table where the storage engine does not
3806
 
    need to know about the change, only the frm will change,
3807
 
    or the storage engine supports performing the alter table
3808
 
    operation directly, on-line without mysql having to copy
3809
 
    the table.
3810
 
*/
3811
 
int mysql_fast_or_online_alter_table(THD *thd,
3812
 
                                     TABLE *table,
3813
 
                                     TABLE *altered_table,
3814
 
                                     HA_CREATE_INFO *create_info,
3815
 
                                     HA_ALTER_INFO *alter_info,
3816
 
                                     HA_ALTER_FLAGS *ha_alter_flags,
3817
 
                                     enum enum_enable_or_disable keys_onoff)
3818
 
{
3819
 
  int error= 0;
3820
 
  bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
3821
 
  TABLE *t_table;
3822
 
 
3823
 
  if (online)
3824
 
  {
3825
 
   /*
3826
 
      Tell the handler to prepare for the online alter
3827
 
    */
3828
 
    if ((error= table->file->alter_table_phase1(thd,
3829
 
                                                altered_table,
3830
 
                                                create_info,
3831
 
                                                alter_info,
3832
 
                                                ha_alter_flags)))
3833
 
    {
3834
 
      goto err;
3835
 
    }
3836
 
 
3837
 
    /*
3838
 
       Tell the storage engine to perform the online alter table
3839
 
       TODO: 
3840
 
       if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
3841
 
       we need to wrap the next call with a DDL lock.
3842
 
     */
3843
 
    if ((error= table->file->alter_table_phase2(thd,
3844
 
                                                altered_table,
3845
 
                                                create_info,
3846
 
                                                alter_info,
3847
 
                                                ha_alter_flags)))
3848
 
    {
3849
 
      goto err;
3850
 
    }
3851
 
  }
3852
 
  /*
3853
 
    The final .frm file is already created as a temporary file
3854
 
    and will be renamed to the original table name.
3855
 
  */
3856
 
  VOID(pthread_mutex_lock(&LOCK_open));
3857
 
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3858
 
  alter_table_manage_keys(table, table->file->indexes_are_disabled(),
3859
 
                          keys_onoff);
3860
 
  close_data_files_and_morph_locks(thd,
3861
 
                                   table->pos_in_table_list->db,
3862
 
                                   table->pos_in_table_list->table_name);
3863
 
  if (mysql_rename_table(NULL,
3864
 
                         altered_table->s->db.str,
3865
 
                         altered_table->s->table_name.str,
3866
 
                         table->s->db.str,
3867
 
                         table->s->table_name.str, FN_FROM_IS_TMP))
3868
 
  {
3869
 
    error= 1;
3870
 
    VOID(pthread_mutex_unlock(&LOCK_open));
3871
 
    goto err;
3872
 
  }
3873
 
  broadcast_refresh();
3874
 
  VOID(pthread_mutex_unlock(&LOCK_open));
3875
 
 
3876
 
  /*
3877
 
    The ALTER TABLE is always in its own transaction.
3878
 
    Commit must not be called while LOCK_open is locked. It could call
3879
 
    wait_if_global_read_lock(), which could create a deadlock if called
3880
 
    with LOCK_open.
3881
 
  */
3882
 
  error= ha_autocommit_or_rollback(thd, 0);
3883
 
 
3884
 
  if (ha_commit(thd))
3885
 
    error=1;
3886
 
  if (error)
3887
 
    goto err;
3888
 
  if (online)
3889
 
  {
3890
 
    VOID(pthread_mutex_lock(&LOCK_open));
3891
 
    if (reopen_table(table))
3892
 
    {
3893
 
      error= -1;
3894
 
      goto err;
3895
 
    }
3896
 
    VOID(pthread_mutex_unlock(&LOCK_open));
3897
 
    t_table= table;
3898
 
 
3899
 
   /*
3900
 
      Tell the handler that the changed frm is on disk and table
3901
 
      has been re-opened
3902
 
   */
3903
 
    if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3904
 
    {
3905
 
      goto err;
3906
 
    }
3907
 
 
3908
 
    /*
3909
 
      We are going to reopen table down on the road, so we have to restore
3910
 
      state of the TABLE object which we used for obtaining of handler
3911
 
      object to make it suitable for reopening.
3912
 
    */
3913
 
    assert(t_table == table);
3914
 
    table->open_placeholder= 1;
3915
 
    VOID(pthread_mutex_lock(&LOCK_open));
3916
 
    close_handle_and_leave_table_as_lock(table);
3917
 
    VOID(pthread_mutex_unlock(&LOCK_open));
3918
 
  }
3919
 
 
3920
 
 err:
3921
 
  if (error)
3922
 
    return(error);
3923
 
  return 0;
3924
 
}
3925
 
 
3926
 
 
3927
 
/**
3928
 
  Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
3929
 
 
3930
 
  This function transforms parse output of ALTER TABLE - lists of
3931
 
  columns and keys to add, drop or modify into, essentially,
3932
 
  CREATE TABLE definition - a list of columns and keys of the new
3933
 
  table. While doing so, it also performs some (bug not all)
3934
 
  semantic checks.
3935
 
 
3936
 
  This function is invoked when we know that we're going to
3937
 
  perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
3938
 
  is not possible, perhaps because the ALTER statement contains
3939
 
  instructions that require change in table data, not only in
3940
 
  table definition or indexes.
3941
 
 
3942
 
  @param[in,out]  thd         thread handle. Used as a memory pool
3943
 
                              and source of environment information.
3944
 
  @param[in]      table       the source table, open and locked
3945
 
                              Used as an interface to the storage engine
3946
 
                              to acquire additional information about
3947
 
                              the original table.
3948
 
  @param[in,out]  create_info A blob with CREATE/ALTER TABLE
3949
 
                              parameters
3950
 
  @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
3951
 
                              Originally create_info was used only in
3952
 
                              CREATE TABLE and alter_info only in ALTER TABLE.
3953
 
                              But since ALTER might end-up doing CREATE,
3954
 
                              this distinction is gone and we just carry
3955
 
                              around two structures.
3956
 
 
3957
 
  @return
3958
 
    Fills various create_info members based on information retrieved
3959
 
    from the storage engine.
3960
 
    Sets create_info->varchar if the table has a VARCHAR column.
3961
 
    Prepares alter_info->create_list and alter_info->key_list with
3962
 
    columns and keys of the new table.
3963
 
  @retval true   error, out of memory or a semantical error in ALTER
3964
 
                 TABLE instructions
3965
 
  @retval false  success
3966
 
*/
3967
 
 
3968
 
static bool
3969
 
mysql_prepare_alter_table(THD *thd, TABLE *table,
3970
 
                          HA_CREATE_INFO *create_info,
3971
 
                          Alter_info *alter_info)
3972
 
{
3973
 
  /* New column definitions are added here */
3974
 
  List<Create_field> new_create_list;
3975
 
  /* New key definitions are added here */
3976
 
  List<Key> new_key_list;
3977
 
  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3978
 
  List_iterator<Create_field> def_it(alter_info->create_list);
3979
 
  List_iterator<Alter_column> alter_it(alter_info->alter_list);
3980
 
  List_iterator<Key> key_it(alter_info->key_list);
3981
 
  List_iterator<Create_field> find_it(new_create_list);
3982
 
  List_iterator<Create_field> field_it(new_create_list);
3983
 
  List<Key_part_spec> key_parts;
3984
 
  uint db_create_options= (table->s->db_create_options
3985
 
                           & ~(HA_OPTION_PACK_RECORD));
3986
 
  uint used_fields= create_info->used_fields;
3987
 
  KEY *key_info=table->key_info;
3988
 
  bool rc= true;
3989
 
 
3990
 
 
3991
 
  create_info->varchar= false;
3992
 
  /* Let new create options override the old ones */
3993
 
  if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3994
 
    create_info->min_rows= table->s->min_rows;
3995
 
  if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3996
 
    create_info->max_rows= table->s->max_rows;
3997
 
  if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3998
 
    create_info->avg_row_length= table->s->avg_row_length;
3999
 
  if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
4000
 
    create_info->block_size= table->s->block_size;
4001
 
  if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
4002
 
    create_info->default_table_charset= table->s->table_charset;
4003
 
  if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
4004
 
    {
4005
 
    /* Table has an autoincrement, copy value to new table */
4006
 
    table->file->info(HA_STATUS_AUTO);
4007
 
    create_info->auto_increment_value= table->file->stats.auto_increment_value;
4008
 
  }
4009
 
  if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4010
 
    create_info->key_block_size= table->s->key_block_size;
4011
 
  if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
4012
 
    create_info->transactional= table->s->transactional;
4013
 
 
4014
 
  restore_record(table, s->default_values);     // Empty record for DEFAULT
4015
 
  Create_field *def;
4016
 
 
4017
 
    /*
4018
 
    First collect all fields from table which isn't in drop_list
4019
 
    */
4020
 
  Field **f_ptr,*field;
4021
 
  for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
4022
 
    {
4023
 
    /* Check if field should be dropped */
4024
 
    Alter_drop *drop;
4025
 
    drop_it.rewind();
4026
 
    while ((drop=drop_it++))
4027
 
    {
4028
 
      if (drop->type == Alter_drop::COLUMN &&
4029
 
          !my_strcasecmp(system_charset_info,field->field_name, drop->name))
4030
 
    {
4031
 
        /* Reset auto_increment value if it was dropped */
4032
 
        if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
4033
 
            !(used_fields & HA_CREATE_USED_AUTO))
4034
 
      {
4035
 
          create_info->auto_increment_value=0;
4036
 
          create_info->used_fields|=HA_CREATE_USED_AUTO;
4037
 
      }
4038
 
        break;
4039
 
    }
4040
 
  }
4041
 
    if (drop)
4042
 
      {
4043
 
      drop_it.remove();
4044
 
      continue;
4045
 
    }
4046
 
    /* Check if field is changed */
4047
 
    def_it.rewind();
4048
 
    while ((def=def_it++))
4049
 
    {
4050
 
      if (def->change &&
4051
 
          !my_strcasecmp(system_charset_info,field->field_name, def->change))
4052
 
        break;
4053
 
    }
4054
 
    if (def)
4055
 
    {                                           // Field is changed
4056
 
      def->field=field;
4057
 
      if (!def->after)
4058
 
        {
4059
 
        new_create_list.push_back(def);
4060
 
        def_it.remove();
4061
 
        }
4062
 
      }
4063
 
      else
4064
 
      {
4065
 
      /*
4066
 
        This field was not dropped and not changed, add it to the list
4067
 
        for the new table.
4068
 
      */
4069
 
      def= new Create_field(field, field);
4070
 
      new_create_list.push_back(def);
4071
 
      alter_it.rewind();                        // Change default if ALTER
4072
 
      Alter_column *alter;
4073
 
      while ((alter=alter_it++))
4074
 
        {
4075
 
        if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
4076
 
          break;
4077
 
        }
4078
 
      if (alter)
4079
 
        {
4080
 
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
4081
 
        {
4082
 
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
4083
 
          goto err;
4084
 
        }
4085
 
        if ((def->def=alter->def))              // Use new default
4086
 
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
4087
 
        else
4088
 
          def->flags|= NO_DEFAULT_VALUE_FLAG;
4089
 
        alter_it.remove();
4090
 
      }
4091
 
    }
4092
 
  }
4093
 
  def_it.rewind();
4094
 
  while ((def=def_it++))                        // Add new columns
4095
 
  {
4096
 
    if (def->change && ! def->field)
4097
 
    {
4098
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
4099
 
      goto err;
4100
 
    }
4101
 
      /*
4102
 
      Check that the DATE/DATETIME not null field we are going to add is
4103
 
      either has a default value or the '0000-00-00' is allowed by the
4104
 
      set sql mode.
4105
 
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
4106
 
      flag to allow ALTER TABLE only if the table to be altered is empty.
4107
 
      */
4108
 
    if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
4109
 
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
4110
 
         !alter_info->datetime_field &&
4111
 
         !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
4112
 
         thd->variables.sql_mode & MODE_NO_ZERO_DATE)
4113
 
    {
4114
 
        alter_info->datetime_field= def;
4115
 
        alter_info->error_if_not_empty= true;
4116
 
    }
4117
 
    if (!def->after)
4118
 
      new_create_list.push_back(def);
4119
 
    else if (def->after == first_keyword)
4120
 
      new_create_list.push_front(def);
4121
 
    else
4122
 
    {
4123
 
      Create_field *find;
4124
 
      find_it.rewind();
4125
 
      while ((find=find_it++))                  // Add new columns
4126
 
      {
4127
 
        if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
4128
 
          break;
4129
 
  }
4130
 
      if (!find)
4131
 
  {
4132
 
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
4133
 
    goto err;
4134
 
  }
4135
 
      find_it.after(def);                       // Put element after this
4136
 
      /*
4137
 
        XXX: hack for Bug#28427.
4138
 
        If column order has changed, force OFFLINE ALTER TABLE
4139
 
        without querying engine capabilities.  If we ever have an
4140
 
        engine that supports online ALTER TABLE CHANGE COLUMN
4141
 
        <name> AFTER <name1> (Falcon?), this fix will effectively
4142
 
        disable the capability.
4143
 
        TODO: detect the situation in compare_tables, behave based
4144
 
        on engine capabilities.
4145
 
      */
4146
 
      if (alter_info->build_method == HA_BUILD_ONLINE)
4147
 
      {
4148
 
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4149
 
        goto err;
4150
 
      }
4151
 
      alter_info->build_method= HA_BUILD_OFFLINE;
4152
 
    }
4153
 
  }
4154
 
  if (alter_info->alter_list.elements)
4155
 
  {
4156
 
    my_error(ER_BAD_FIELD_ERROR, MYF(0),
4157
 
             alter_info->alter_list.head()->name, table->s->table_name.str);
4158
 
    goto err;
4159
 
    }
4160
 
  if (!new_create_list.elements)
4161
 
    {
4162
 
    my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
4163
 
               MYF(0));
4164
 
    goto err;
4165
 
    }
4166
 
 
4167
 
    /*
4168
 
    Collect all keys which isn't in drop list. Add only those
4169
 
    for which some fields exists.
4170
 
    */
4171
 
 
4172
 
  for (uint i=0 ; i < table->s->keys ; i++,key_info++)
4173
 
    {
4174
 
    char *key_name= key_info->name;
4175
 
    Alter_drop *drop;
4176
 
    drop_it.rewind();
4177
 
    while ((drop=drop_it++))
4178
 
      {
4179
 
      if (drop->type == Alter_drop::KEY &&
4180
 
          !my_strcasecmp(system_charset_info,key_name, drop->name))
4181
 
        break;
4182
 
      }
4183
 
    if (drop)
4184
 
        {
4185
 
      drop_it.remove();
4186
 
      continue;
4187
 
    }
4188
 
 
4189
 
    KEY_PART_INFO *key_part= key_info->key_part;
4190
 
    key_parts.empty();
4191
 
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
4192
 
    {
4193
 
      if (!key_part->field)
4194
 
        continue;                               // Wrong field (from UNIREG)
4195
 
      const char *key_part_name=key_part->field->field_name;
4196
 
      Create_field *cfield;
4197
 
      field_it.rewind();
4198
 
      while ((cfield=field_it++))
4199
 
    {
4200
 
        if (cfield->change)
4201
 
    {
4202
 
          if (!my_strcasecmp(system_charset_info, key_part_name,
4203
 
                             cfield->change))
4204
 
            break;
4205
 
        }
4206
 
        else if (!my_strcasecmp(system_charset_info,
4207
 
                                key_part_name, cfield->field_name))
4208
 
          break;
4209
 
      }
4210
 
      if (!cfield)
4211
 
        continue;                               // Field is removed
4212
 
      uint key_part_length=key_part->length;
4213
 
      if (cfield->field)                        // Not new field
4214
 
      {
4215
 
        /*
4216
 
          If the field can't have only a part used in a key according to its
4217
 
          new type, or should not be used partially according to its
4218
 
          previous type, or the field length is less than the key part
4219
 
          length, unset the key part length.
4220
 
 
4221
 
          We also unset the key part length if it is the same as the
4222
 
          old field's length, so the whole new field will be used.
4223
 
 
4224
 
          BLOBs may have cfield->length == 0, which is why we test it before
4225
 
          checking whether cfield->length < key_part_length (in chars).
4226
 
         */
4227
 
        if (!Field::type_can_have_key_part(cfield->field->type()) ||
4228
 
            !Field::type_can_have_key_part(cfield->sql_type) ||
4229
 
            (cfield->field->field_length == key_part_length &&
4230
 
             !f_is_blob(key_part->key_type)) ||
4231
 
            (cfield->length && (cfield->length < key_part_length /
4232
 
                                key_part->field->charset()->mbmaxlen)))
4233
 
          key_part_length= 0;                   // Use whole field
4234
 
      }
4235
 
      key_part_length /= key_part->field->charset()->mbmaxlen;
4236
 
      key_parts.push_back(new Key_part_spec(cfield->field_name,
4237
 
                                            strlen(cfield->field_name),
4238
 
                                            key_part_length));
4239
 
    }
4240
 
    if (key_parts.elements)
4241
 
    {
4242
 
      KEY_CREATE_INFO key_create_info;
4243
 
      Key *key;
4244
 
      enum Key::Keytype key_type;
4245
 
      memset(&key_create_info, 0, sizeof(key_create_info));
4246
 
 
4247
 
      key_create_info.algorithm= key_info->algorithm;
4248
 
      if (key_info->flags & HA_USES_BLOCK_SIZE)
4249
 
        key_create_info.block_size= key_info->block_size;
4250
 
      if (key_info->flags & HA_USES_COMMENT)
4251
 
        key_create_info.comment= key_info->comment;
4252
 
 
4253
 
      if (key_info->flags & HA_NOSAME)
4254
 
      {
4255
 
        if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
4256
 
          key_type= Key::PRIMARY;
4257
 
        else
4258
 
          key_type= Key::UNIQUE;
4259
 
      }
4260
 
      else
4261
 
        key_type= Key::MULTIPLE;
4262
 
 
4263
 
      key= new Key(key_type, key_name, strlen(key_name),
4264
 
                   &key_create_info,
4265
 
                   test(key_info->flags & HA_GENERATED_KEY),
4266
 
                   key_parts);
4267
 
      new_key_list.push_back(key);
4268
 
    }
4269
 
  }
4270
 
  {
4271
 
    Key *key;
4272
 
    while ((key=key_it++))                      // Add new keys
4273
 
    {
4274
 
      if (key->type != Key::FOREIGN_KEY)
4275
 
        new_key_list.push_back(key);
4276
 
      if (key->name.str &&
4277
 
          !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
4278
 
      {
4279
 
        my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
4280
 
        goto err;
4281
 
      }
4282
 
    }
4283
 
  }
4284
 
 
4285
 
  if (alter_info->drop_list.elements)
4286
 
  {
4287
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4288
 
             alter_info->drop_list.head()->name);
4289
 
    goto err;
4290
 
  }
4291
 
  if (alter_info->alter_list.elements)
4292
 
  {
4293
 
    my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4294
 
             alter_info->alter_list.head()->name);
4295
 
    goto err;
4296
 
  }
4297
 
 
4298
 
  if (!create_info->comment.str)
4299
 
  {
4300
 
    create_info->comment.str= table->s->comment.str;
4301
 
    create_info->comment.length= table->s->comment.length;
4302
 
  }
4303
 
 
4304
 
  table->file->update_create_info(create_info);
4305
 
  if ((create_info->table_options &
4306
 
       (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
4307
 
      (used_fields & HA_CREATE_USED_PACK_KEYS))
4308
 
    db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
4309
 
  if (create_info->table_options &
4310
 
      (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
4311
 
    db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
4312
 
  if (create_info->table_options &
4313
 
      (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
4314
 
    db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
4315
 
                          HA_OPTION_NO_DELAY_KEY_WRITE);
4316
 
  create_info->table_options|= db_create_options;
4317
 
 
4318
 
  if (table->s->tmp_table)
4319
 
    create_info->options|=HA_LEX_CREATE_TMP_TABLE;
4320
 
 
4321
 
  rc= false;
4322
 
  alter_info->create_list.swap(new_create_list);
4323
 
  alter_info->key_list.swap(new_key_list);
4324
 
err:
4325
 
  return(rc);
4326
 
}
4327
 
 
4328
 
 
4329
 
/*
4330
 
  Alter table
4331
 
 
4332
 
  SYNOPSIS
4333
 
    mysql_alter_table()
4334
 
      thd              Thread handle
4335
 
      new_db           If there is a RENAME clause
4336
 
      new_name         If there is a RENAME clause
4337
 
      create_info      Information from the parsing phase about new
4338
 
                       table properties.
4339
 
      table_list       The table to change.
4340
 
      alter_info       Lists of fields, keys to be changed, added
4341
 
                       or dropped.
4342
 
      order_num        How many ORDER BY fields has been specified.
4343
 
      order            List of fields to ORDER BY.
4344
 
      ignore           Whether we have ALTER IGNORE TABLE
4345
 
 
4346
 
  DESCRIPTION
4347
 
    This is a veery long function and is everything but the kitchen sink :)
4348
 
    It is used to alter a table and not only by ALTER TABLE but also
4349
 
    CREATE|DROP INDEX are mapped on this function.
4350
 
 
4351
 
    When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
4352
 
    or both, then this function short cuts its operation by renaming
4353
 
    the table and/or enabling/disabling the keys. In this case, the FRM is
4354
 
    not changed, directly by mysql_alter_table. However, if there is a
4355
 
    RENAME + change of a field, or an index, the short cut is not used.
4356
 
    See how `create_list` is used to generate the new FRM regarding the
4357
 
    structure of the fields. The same is done for the indices of the table.
4358
 
 
4359
 
    Important is the fact, that this function tries to do as little work as
4360
 
    possible, by finding out whether a intermediate table is needed to copy
4361
 
    data into and when finishing the altering to use it as the original table.
4362
 
    For this reason the function compare_tables() is called, which decides
4363
 
    based on all kind of data how similar are the new and the original
4364
 
    tables.
4365
 
 
4366
 
  RETURN VALUES
4367
 
    false  OK
4368
 
    true   Error
4369
 
*/
4370
 
 
4371
 
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4372
 
                       HA_CREATE_INFO *create_info,
4373
 
                       TABLE_LIST *table_list,
4374
 
                       Alter_info *alter_info,
4375
 
                       uint order_num, ORDER *order, bool ignore)
4376
 
{
4377
 
  TABLE *table, *new_table=0, *name_lock= 0;;
4378
 
  int error= 0;
4379
 
  char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4380
 
  char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4381
 
  char path[FN_REFLEN];
4382
 
  ha_rows copied= 0,deleted= 0;
4383
 
  handlerton *old_db_type, *new_db_type, *save_old_db_type;
4384
 
  legacy_db_type table_type;
4385
 
  frm_type_enum frm_type;
4386
 
 
4387
 
  if (table_list && table_list->schema_table)
4388
 
  {
4389
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
4390
 
    return(true);
4391
 
  }
4392
 
 
4393
 
  /*
4394
 
    Assign variables table_name, new_name, db, new_db, path
4395
 
    to simplify further comparisons: we want to see if it's a RENAME
4396
 
    later just by comparing the pointers, avoiding the need for strcmp.
4397
 
  */
4398
 
  thd_proc_info(thd, "init");
4399
 
  table_name=table_list->table_name;
4400
 
  alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
4401
 
  db=table_list->db;
4402
 
  if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
4403
 
    new_db= db;
4404
 
  build_table_filename(path, sizeof(path), db, table_name, "", 0);
4405
 
 
4406
 
  mysql_ha_rm_tables(thd, table_list, false);
4407
 
 
4408
 
  /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
4409
 
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4410
 
    /* Conditionally writes to binlog. */
4411
 
    return(mysql_discard_or_import_tablespace(thd,table_list,
4412
 
                                              alter_info->tablespace_op));
4413
 
  strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db, 
4414
 
           "/", table_name, reg_ext, NullS);
4415
 
  (void) unpack_filename(new_name_buff, new_name_buff);
4416
 
  /*
4417
 
    If this is just a rename of a view, short cut to the
4418
 
    following scenario: 1) lock LOCK_open 2) do a RENAME
4419
 
    2) unlock LOCK_open.
4420
 
    This is a copy-paste added to make sure
4421
 
    ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
4422
 
    as an independent branch in mysql_execute_command. The need
4423
 
    for a copy-paste arose because the main code flow of ALTER TABLE
4424
 
    ... RENAME tries to use open_ltable, which does not work for views
4425
 
    (open_ltable was never modified to merge table lists of child tables
4426
 
    into the main table list, like open_tables does).
4427
 
    This code is wrong and will be removed, please do not copy.
4428
 
  */
4429
 
  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
4430
 
 
4431
 
  if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
4432
 
    return(true);
4433
 
  table->use_all_columns();
4434
 
 
4435
 
  /* Check that we are not trying to rename to an existing table */
4436
 
  if (new_name)
4437
 
  {
4438
 
    stpcpy(new_name_buff,new_name);
4439
 
    stpcpy(new_alias= new_alias_buff, new_name);
4440
 
    if (lower_case_table_names)
4441
 
    {
4442
 
      if (lower_case_table_names != 2)
4443
 
      {
4444
 
        my_casedn_str(files_charset_info, new_name_buff);
4445
 
        new_alias= new_name;                    // Create lower case table name
4446
 
      }
4447
 
      my_casedn_str(files_charset_info, new_name);
4448
 
    }
4449
 
    if (new_db == db &&
4450
 
        !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
4451
 
    {
4452
 
      /*
4453
 
        Source and destination table names are equal: make later check
4454
 
        easier.
4455
 
      */
4456
 
      new_alias= new_name= table_name;
4457
 
    }
4458
 
    else
4459
 
    {
4460
 
      if (table->s->tmp_table != NO_TMP_TABLE)
4461
 
      {
4462
 
        if (find_temporary_table(thd,new_db,new_name_buff))
4463
 
        {
4464
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
4465
 
          return(true);
4466
 
        }
4467
 
      }
4468
 
      else
4469
 
      {
4470
 
        if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
4471
 
          return(true);
4472
 
        if (!name_lock)
4473
 
        {
4474
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4475
 
          return(true);
4476
 
        }
4477
 
 
4478
 
        build_table_filename(new_name_buff, sizeof(new_name_buff),
4479
 
                             new_db, new_name_buff, reg_ext, 0);
4480
 
        if (!access(new_name_buff, F_OK))
4481
 
        {
4482
 
          /* Table will be closed in do_command() */
4483
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4484
 
          goto err;
4485
 
        }
4486
 
      }
4487
 
    }
4488
 
  }
4489
 
  else
4490
 
  {
4491
 
    new_alias= (lower_case_table_names == 2) ? alias : table_name;
4492
 
    new_name= table_name;
4493
 
  }
4494
 
 
4495
 
  old_db_type= table->s->db_type();
4496
 
  if (!create_info->db_type)
4497
 
  {
4498
 
    create_info->db_type= old_db_type;
4499
 
  }
4500
 
 
4501
 
  if (check_engine(thd, new_name, create_info))
4502
 
    goto err;
4503
 
  new_db_type= create_info->db_type;
4504
 
 
4505
 
  if (new_db_type != old_db_type &&
4506
 
      !table->file->can_switch_engines())
4507
 
  {
4508
 
    assert(0);
4509
 
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
4510
 
    goto err;
4511
 
  }
4512
 
 
4513
 
  if (create_info->row_type == ROW_TYPE_NOT_USED)
4514
 
    create_info->row_type= table->s->row_type;
4515
 
 
4516
 
  if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
4517
 
      ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
4518
 
  {
4519
 
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
4520
 
    goto err;
4521
 
  }
4522
 
 
4523
 
  thd_proc_info(thd, "setup");
4524
 
  if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
4525
 
      !table->s->tmp_table) // no need to touch frm
4526
 
  {
4527
 
    switch (alter_info->keys_onoff) {
4528
 
    case LEAVE_AS_IS:
4529
 
      break;
4530
 
    case ENABLE:
4531
 
      /*
4532
 
        wait_while_table_is_used() ensures that table being altered is
4533
 
        opened only by this thread and that TABLE::TABLE_SHARE::version
4534
 
        of TABLE object corresponding to this table is 0.
4535
 
        The latter guarantees that no DML statement will open this table
4536
 
        until ALTER TABLE finishes (i.e. until close_thread_tables())
4537
 
        while the fact that the table is still open gives us protection
4538
 
        from concurrent DDL statements.
4539
 
      */
4540
 
      VOID(pthread_mutex_lock(&LOCK_open));
4541
 
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4542
 
      VOID(pthread_mutex_unlock(&LOCK_open));
4543
 
      error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4544
 
      /* COND_refresh will be signaled in close_thread_tables() */
4545
 
      break;
4546
 
    case DISABLE:
4547
 
      VOID(pthread_mutex_lock(&LOCK_open));
4548
 
      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4549
 
      VOID(pthread_mutex_unlock(&LOCK_open));
4550
 
      error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4551
 
      /* COND_refresh will be signaled in close_thread_tables() */
4552
 
      break;
4553
 
    default:
4554
 
      assert(false);
4555
 
      error= 0;
4556
 
      break;
4557
 
    }
4558
 
    if (error == HA_ERR_WRONG_COMMAND)
4559
 
    {
4560
 
      error= 0;
4561
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4562
 
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4563
 
                          table->alias);
4564
 
    }
4565
 
 
4566
 
    VOID(pthread_mutex_lock(&LOCK_open));
4567
 
    /*
4568
 
      Unlike to the above case close_cached_table() below will remove ALL
4569
 
      instances of TABLE from table cache (it will also remove table lock
4570
 
      held by this thread). So to make actual table renaming and writing
4571
 
      to binlog atomic we have to put them into the same critical section
4572
 
      protected by LOCK_open mutex. This also removes gap for races between
4573
 
      access() and mysql_rename_table() calls.
4574
 
    */
4575
 
 
4576
 
    if (!error && (new_name != table_name || new_db != db))
4577
 
    {
4578
 
      thd_proc_info(thd, "rename");
4579
 
      /*
4580
 
        Then do a 'simple' rename of the table. First we need to close all
4581
 
        instances of 'source' table.
4582
 
      */
4583
 
      close_cached_table(thd, table);
4584
 
      /*
4585
 
        Then, we want check once again that target table does not exist.
4586
 
        Actually the order of these two steps does not matter since
4587
 
        earlier we took name-lock on the target table, so we do them
4588
 
        in this particular order only to be consistent with 5.0, in which
4589
 
        we don't take this name-lock and where this order really matters.
4590
 
        TODO: Investigate if we need this access() check at all.
4591
 
      */
4592
 
      if (!access(new_name_buff,F_OK))
4593
 
      {
4594
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
4595
 
        error= -1;
4596
 
      }
4597
 
      else
4598
 
      {
4599
 
        *fn_ext(new_name)=0;
4600
 
        if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
4601
 
          error= -1;
4602
 
        else if (0)
4603
 
      {
4604
 
          VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
4605
 
                                  table_name, 0));
4606
 
          error= -1;
4607
 
      }
4608
 
    }
4609
 
  }
4610
 
 
4611
 
    if (error == HA_ERR_WRONG_COMMAND)
4612
 
  {
4613
 
      error= 0;
4614
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4615
 
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4616
 
                          table->alias);
4617
 
  }
4618
 
 
4619
 
    if (!error)
4620
 
    {
4621
 
      write_bin_log(thd, true, thd->query, thd->query_length);
4622
 
      my_ok(thd);
4623
 
  }
4624
 
    else if (error > 0)
4625
 
  {
4626
 
      table->file->print_error(error, MYF(0));
4627
 
      error= -1;
4628
 
    }
4629
 
    if (name_lock)
4630
 
      unlink_open_table(thd, name_lock, false);
4631
 
    VOID(pthread_mutex_unlock(&LOCK_open));
4632
 
    table_list->table= NULL;                    // For query cache
4633
 
    return(error);
4634
 
  }
4635
 
 
4636
 
  /* We have to do full alter table. */
4637
 
 
4638
 
    /*
4639
 
    If the old table had partitions and we are doing ALTER TABLE ...
4640
 
    engine= <new_engine>, the new table must preserve the original
4641
 
    partitioning. That means that the new engine is still the
4642
 
    partitioning engine, not the engine specified in the parser.
4643
 
    This is discovered  in prep_alter_part_table, which in such case
4644
 
    updates create_info->db_type.
4645
 
    Now we need to update the stack copy of create_info->db_type,
4646
 
    as otherwise we won't be able to correctly move the files of the
4647
 
    temporary table to the result table files.
4648
 
  */
4649
 
  new_db_type= create_info->db_type;
4650
 
 
4651
 
  if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4652
 
      goto err;
4653
 
 
4654
 
  set_table_default_charset(thd, create_info, db);
4655
 
 
4656
 
 
4657
 
  if (thd->variables.old_alter_table
4658
 
      || (table->s->db_type() != create_info->db_type)
4659
 
     )
4660
 
  {
4661
 
    if (alter_info->build_method == HA_BUILD_ONLINE)
4662
 
    {
4663
 
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4664
 
      goto err;
4665
 
    }
4666
 
    alter_info->build_method= HA_BUILD_OFFLINE;
4667
 
  }
4668
 
 
4669
 
  if (alter_info->build_method != HA_BUILD_OFFLINE)
4670
 
  {
4671
 
    TABLE *altered_table= 0;
4672
 
    HA_ALTER_INFO ha_alter_info;
4673
 
    HA_ALTER_FLAGS ha_alter_flags;
4674
 
    uint table_changes= IS_EQUAL_YES;
4675
 
    bool need_copy_table= true;
4676
 
    /* Check how much the tables differ. */
4677
 
    if (compare_tables(thd, table, alter_info,
4678
 
                       create_info, order_num,
4679
 
                       &ha_alter_flags,
4680
 
                       &ha_alter_info,
4681
 
                       &table_changes))
4682
 
    {
4683
 
      return(true);
4684
 
    }
4685
 
 
4686
 
    /*
4687
 
      Check if storage engine supports altering the table
4688
 
      on-line.
4689
 
    */
4690
 
 
4691
 
 
4692
 
    /*
4693
 
      If table is not renamed, changed database and
4694
 
      some change was detected then check if engine
4695
 
      can do the change on-line
4696
 
    */
4697
 
    if (new_name == table_name && new_db == db &&
4698
 
        ha_alter_flags.is_set())
4699
 
    {
4700
 
      Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4701
 
 
4702
 
      /*
4703
 
        If no table rename,
4704
 
        check if table can be altered on-line
4705
 
      */
4706
 
      if (!(altered_table= create_altered_table(thd,
4707
 
                                                table,
4708
 
                                                new_db,
4709
 
                                                create_info,
4710
 
                                                &tmp_alter_info,
4711
 
                                                !strcmp(db, new_db))))
4712
 
        goto err;
4713
 
 
4714
 
      switch (table->file->check_if_supported_alter(altered_table,
4715
 
                                                    create_info,
4716
 
                                                    &ha_alter_flags,
4717
 
                                                    table_changes)) {
4718
 
      case HA_ALTER_SUPPORTED_WAIT_LOCK:
4719
 
      case HA_ALTER_SUPPORTED_NO_LOCK:
4720
 
        /*
4721
 
          @todo: Currently we always acquire an exclusive name
4722
 
          lock on the table metadata when performing fast or online
4723
 
          ALTER TABLE. In future we may consider this unnecessary,
4724
 
          and narrow the scope of the exclusive name lock to only
4725
 
          cover manipulation with .frms. Storage engine API
4726
 
          call check_if_supported_alter has provision for this
4727
 
          already now.
4728
 
        */
4729
 
        need_copy_table= false;
4730
 
        break;
4731
 
      case HA_ALTER_NOT_SUPPORTED:
4732
 
        if (alter_info->build_method == HA_BUILD_ONLINE)
4733
 
        {
4734
 
          my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4735
 
          close_temporary_table(thd, altered_table, 1, 1);
4736
 
          goto err;
4737
 
        }
4738
 
        need_copy_table= true;
4739
 
        break;
4740
 
      case HA_ALTER_ERROR:
4741
 
      default:
4742
 
        close_temporary_table(thd, altered_table, 1, 1);
4743
 
        goto err;
4744
 
      }
4745
 
 
4746
 
    }
4747
 
    /* TODO need to check if changes can be handled as fast ALTER TABLE */
4748
 
    if (!altered_table)
4749
 
      need_copy_table= true;
4750
 
 
4751
 
    if (!need_copy_table)
4752
 
    {
4753
 
      error= mysql_fast_or_online_alter_table(thd,
4754
 
                                              table,
4755
 
                                              altered_table,
4756
 
                                              create_info,
4757
 
                                              &ha_alter_info,
4758
 
                                              &ha_alter_flags,
4759
 
                                              alter_info->keys_onoff);
4760
 
      if (thd->lock)
4761
 
      {
4762
 
        mysql_unlock_tables(thd, thd->lock);
4763
 
        thd->lock=0;
4764
 
      }
4765
 
      close_temporary_table(thd, altered_table, 1, 1);
4766
 
 
4767
 
      if (error)
4768
 
      {
4769
 
        switch (error) {
4770
 
        case(-1):
4771
 
          goto err_with_placeholders;
4772
 
        default:
4773
 
          goto err;
4774
 
        }
4775
 
      }
4776
 
      else
4777
 
      {
4778
 
        pthread_mutex_lock(&LOCK_open);
4779
 
        goto end_online;
4780
 
      }
4781
 
    }
4782
 
 
4783
 
    if (altered_table)
4784
 
      close_temporary_table(thd, altered_table, 1, 1);
4785
 
  }
4786
 
 
4787
 
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4788
 
           current_pid, thd->thread_id);
4789
 
  /* Safety fix for innodb */
4790
 
  if (lower_case_table_names)
4791
 
    my_casedn_str(files_charset_info, tmp_name);
4792
 
 
4793
 
 
4794
 
  /* Create a temporary table with the new format */
4795
 
  if ((error= create_temporary_table(thd, table, new_db, tmp_name, 
4796
 
                                     create_info, alter_info, 
4797
 
                                     !strcmp(db, new_db))))
4798
 
  {
4799
 
    goto err;
4800
 
  }
4801
 
 
4802
 
  /* Open the table so we need to copy the data to it. */
4803
 
  if (table->s->tmp_table)
4804
 
  {
4805
 
    TABLE_LIST tbl;
4806
 
    memset(&tbl, 0, sizeof(tbl));
4807
 
    tbl.db= new_db;
4808
 
    tbl.table_name= tbl.alias= tmp_name;
4809
 
    /* Table is in thd->temporary_tables */
4810
 
    new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
4811
 
                          DRIZZLE_LOCK_IGNORE_FLUSH);
4812
 
  }
4813
 
  else
4814
 
  {
4815
 
    char path[FN_REFLEN];
4816
 
    /* table is a normal table: Create temporary table in same directory */
4817
 
    build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4818
 
                         FN_IS_TMP);
4819
 
    /* Open our intermediate table */
4820
 
    new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4821
 
  }
4822
 
  if (!new_table)
4823
 
    goto err1;
4824
 
 
4825
 
  /* Copy the data if necessary. */
4826
 
  thd->count_cuted_fields= CHECK_FIELD_WARN;    // calc cuted fields
4827
 
  thd->cuted_fields=0L;
4828
 
  thd_proc_info(thd, "copy to tmp table");
4829
 
  copied=deleted=0;
4830
 
  /*
4831
 
    We do not copy data for MERGE tables. Only the children have data.
4832
 
    MERGE tables have HA_NO_COPY_ON_ALTER set.
4833
 
  */
4834
 
  if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
4835
 
  {
4836
 
    /* We don't want update TIMESTAMP fields during ALTER TABLE. */
4837
 
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
4838
 
    new_table->next_number_field=new_table->found_next_number_field;
4839
 
    error= copy_data_between_tables(table, new_table,
4840
 
                                    alter_info->create_list, ignore,
4841
 
                                   order_num, order, &copied, &deleted,
4842
 
                                    alter_info->keys_onoff,
4843
 
                                    alter_info->error_if_not_empty);
4844
 
  }
4845
 
  else
4846
 
  {
4847
 
    VOID(pthread_mutex_lock(&LOCK_open));
4848
 
    wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4849
 
    VOID(pthread_mutex_unlock(&LOCK_open));
4850
 
    alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4851
 
                            alter_info->keys_onoff);
4852
 
    error= ha_autocommit_or_rollback(thd, 0);
4853
 
    if (end_active_trans(thd))
4854
 
      error= 1;
4855
 
  }
4856
 
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
4857
 
 
4858
 
  if (table->s->tmp_table != NO_TMP_TABLE)
4859
 
  {
4860
 
    /* We changed a temporary table */
4861
 
    if (error)
4862
 
      goto err1;
4863
 
    /* Close lock if this is a transactional table */
4864
 
    if (thd->lock)
4865
 
    {
4866
 
      mysql_unlock_tables(thd, thd->lock);
4867
 
      thd->lock=0;
4868
 
    }
4869
 
    /* Remove link to old table and rename the new one */
4870
 
    close_temporary_table(thd, table, 1, 1);
4871
 
    /* Should pass the 'new_name' as we store table name in the cache */
4872
 
    if (rename_temporary_table(thd, new_table, new_db, new_name))
4873
 
      goto err1;
4874
 
    /* We don't replicate alter table statement on temporary tables */
4875
 
    if (!thd->current_stmt_binlog_row_based)
4876
 
      write_bin_log(thd, true, thd->query, thd->query_length);
4877
 
    goto end_temporary;
4878
 
  }
4879
 
 
4880
 
  if (new_table)
4881
 
  {
4882
 
    /*
4883
 
      Close the intermediate table that will be the new table.
4884
 
      Note that MERGE tables do not have their children attached here.
4885
 
    */
4886
 
    intern_close_table(new_table);
4887
 
    my_free(new_table,MYF(0));
4888
 
  }
4889
 
  VOID(pthread_mutex_lock(&LOCK_open));
4890
 
  if (error)
4891
 
  {
4892
 
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4893
 
    VOID(pthread_mutex_unlock(&LOCK_open));
4894
 
    goto err;
4895
 
  }
4896
 
 
4897
 
  /*
4898
 
    Data is copied. Now we:
4899
 
    1) Wait until all other threads close old version of table.
4900
 
    2) Close instances of table open by this thread and replace them
4901
 
       with exclusive name-locks.
4902
 
    3) Rename the old table to a temp name, rename the new one to the
4903
 
       old name.
4904
 
    4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
4905
 
       we reopen new version of table.
4906
 
    5) Write statement to the binary log.
4907
 
    6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
4908
 
       remove name-locks from list of open tables and table cache.
4909
 
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4910
 
       call to remove name-locks from table cache and list of open table.
4911
 
  */
4912
 
 
4913
 
  thd_proc_info(thd, "rename result table");
4914
 
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
4915
 
           current_pid, thd->thread_id);
4916
 
  if (lower_case_table_names)
4917
 
    my_casedn_str(files_charset_info, old_name);
4918
 
 
4919
 
  wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
4920
 
  close_data_files_and_morph_locks(thd, db, table_name);
4921
 
 
4922
 
  error=0;
4923
 
  save_old_db_type= old_db_type;
4924
 
 
4925
 
  /*
4926
 
    This leads to the storage engine (SE) not being notified for renames in
4927
 
    mysql_rename_table(), because we just juggle with the FRM and nothing
4928
 
    more. If we have an intermediate table, then we notify the SE that
4929
 
    it should become the actual table. Later, we will recycle the old table.
4930
 
    However, in case of ALTER TABLE RENAME there might be no intermediate
4931
 
    table. This is when the old and new tables are compatible, according to
4932
 
    compare_table(). Then, we need one additional call to
4933
 
    mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
4934
 
    actual rename in the SE and the FRM is not touched. Note that, if the
4935
 
    table is renamed and the SE is also changed, then an intermediate table
4936
 
    is created and the additional call will not take place.
4937
 
  */
4938
 
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
4939
 
                         FN_TO_IS_TMP))
4940
 
  {
4941
 
    error=1;
4942
 
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4943
 
  }
4944
 
  else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
4945
 
                              new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
4946
 
  {
4947
 
    /* Try to get everything back. */
4948
 
    error=1;
4949
 
    VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
4950
 
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4951
 
    VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
4952
 
                            FN_FROM_IS_TMP));
4953
 
  }
4954
 
 
4955
 
  if (error)
4956
 
  {
4957
 
    /* This shouldn't happen. But let us play it safe. */
4958
 
    goto err_with_placeholders;
4959
 
  }
4960
 
 
4961
 
  VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
4962
 
 
4963
 
end_online:
4964
 
  if (thd->locked_tables && new_name == table_name && new_db == db)
4965
 
  {
4966
 
    thd->in_lock_tables= 1;
4967
 
    error= reopen_tables(thd, 1, 1);
4968
 
    thd->in_lock_tables= 0;
4969
 
    if (error)
4970
 
      goto err_with_placeholders;
4971
 
  }
4972
 
  VOID(pthread_mutex_unlock(&LOCK_open));
4973
 
 
4974
 
  thd_proc_info(thd, "end");
4975
 
 
4976
 
  ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
4977
 
                      thd->query, thd->query_length,
4978
 
                      db, table_name);
4979
 
 
4980
 
  assert(!(mysql_bin_log.is_open() &&
4981
 
                thd->current_stmt_binlog_row_based &&
4982
 
                (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
4983
 
  write_bin_log(thd, true, thd->query, thd->query_length);
4984
 
 
4985
 
  if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4986
 
  {
4987
 
    /*
4988
 
      For the alter table to be properly flushed to the logs, we
4989
 
      have to open the new table.  If not, we get a problem on server
4990
 
      shutdown. But we do not need to attach MERGE children.
4991
 
    */
4992
 
    char path[FN_REFLEN];
4993
 
    TABLE *t_table;
4994
 
    build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
4995
 
    t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4996
 
    if (t_table)
4997
 
    {
4998
 
      intern_close_table(t_table);
4999
 
      my_free(t_table, MYF(0));
5000
 
    }
5001
 
    else
5002
 
      sql_print_warning("Could not open table %s.%s after rename\n",
5003
 
                        new_db,table_name);
5004
 
    ha_flush_logs(old_db_type);
5005
 
  }
5006
 
  table_list->table=0;                          // For query cache
5007
 
 
5008
 
  if (thd->locked_tables && (new_name != table_name || new_db != db))
5009
 
  {
5010
 
    /*
5011
 
      If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
5012
 
      to remove placeholders for the old table and for the target table
5013
 
      from the list of open tables and table cache. If we are not under
5014
 
      LOCK TABLES we can rely on close_thread_tables() doing this job.
5015
 
    */
5016
 
    pthread_mutex_lock(&LOCK_open);
5017
 
    unlink_open_table(thd, table, false);
5018
 
    unlink_open_table(thd, name_lock, false);
5019
 
    pthread_mutex_unlock(&LOCK_open);
5020
 
  }
5021
 
 
5022
 
end_temporary:
5023
 
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5024
 
           (ulong) (copied + deleted), (ulong) deleted,
5025
 
           (ulong) thd->cuted_fields);
5026
 
  my_ok(thd, copied + deleted, 0L, tmp_name);
5027
 
  thd->some_tables_deleted=0;
5028
 
  return(false);
5029
 
 
5030
 
err1:
5031
 
  if (new_table)
5032
 
  {
5033
 
    /* close_temporary_table() frees the new_table pointer. */
5034
 
    close_temporary_table(thd, new_table, 1, 1);
5035
 
  }
5036
 
  else
5037
 
    VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5038
 
 
5039
 
err:
5040
 
  /*
5041
 
    No default value was provided for a DATE/DATETIME field, the
5042
 
    current sql_mode doesn't allow the '0000-00-00' value and
5043
 
    the table to be altered isn't empty.
5044
 
    Report error here.
5045
 
  */
5046
 
  if (alter_info->error_if_not_empty && thd->row_count)
5047
 
  {
5048
 
    const char *f_val= 0;
5049
 
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
5050
 
    switch (alter_info->datetime_field->sql_type)
5051
 
    {
5052
 
      case DRIZZLE_TYPE_NEWDATE:
5053
 
        f_val= "0000-00-00";
5054
 
        t_type= DRIZZLE_TIMESTAMP_DATE;
5055
 
        break;
5056
 
      case DRIZZLE_TYPE_DATETIME:
5057
 
        f_val= "0000-00-00 00:00:00";
5058
 
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
5059
 
        break;
5060
 
      default:
5061
 
        /* Shouldn't get here. */
5062
 
        assert(0);
5063
 
    }
5064
 
    bool save_abort_on_warning= thd->abort_on_warning;
5065
 
    thd->abort_on_warning= true;
5066
 
    make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5067
 
                                 f_val, strlength(f_val), t_type,
5068
 
                                 alter_info->datetime_field->field_name);
5069
 
    thd->abort_on_warning= save_abort_on_warning;
5070
 
  }
5071
 
  if (name_lock)
5072
 
  {
5073
 
    pthread_mutex_lock(&LOCK_open);
5074
 
    unlink_open_table(thd, name_lock, false);
5075
 
    pthread_mutex_unlock(&LOCK_open);
5076
 
  }
5077
 
  return(true);
5078
 
 
5079
 
err_with_placeholders:
5080
 
  /*
5081
 
    An error happened while we were holding exclusive name-lock on table
5082
 
    being altered. To be safe under LOCK TABLES we should remove placeholders
5083
 
    from list of open tables list and table cache.
5084
 
  */
5085
 
  unlink_open_table(thd, table, false);
5086
 
  if (name_lock)
5087
 
    unlink_open_table(thd, name_lock, false);
5088
 
  VOID(pthread_mutex_unlock(&LOCK_open));
5089
 
  return(true);
5090
 
}
5091
 
/* mysql_alter_table */
5092
 
 
5093
 
static int
5094
 
copy_data_between_tables(TABLE *from,TABLE *to,
5095
 
                         List<Create_field> &create,
5096
 
                         bool ignore,
5097
 
                         uint order_num, ORDER *order,
5098
 
                         ha_rows *copied,
5099
 
                         ha_rows *deleted,
5100
 
                         enum enum_enable_or_disable keys_onoff,
5101
 
                         bool error_if_not_empty)
5102
 
{
5103
 
  int error;
5104
 
  Copy_field *copy,*copy_end;
5105
 
  ulong found_count,delete_count;
5106
 
  THD *thd= current_thd;
5107
 
  uint length= 0;
5108
 
  SORT_FIELD *sortorder;
5109
 
  READ_RECORD info;
5110
 
  TABLE_LIST   tables;
5111
 
  List<Item>   fields;
5112
 
  List<Item>   all_fields;
5113
 
  ha_rows examined_rows;
5114
 
  bool auto_increment_field_copied= 0;
5115
 
  ulong save_sql_mode;
5116
 
  uint64_t prev_insert_id;
5117
 
 
5118
 
  /*
5119
 
    Turn off recovery logging since rollback of an alter table is to
5120
 
    delete the new table so there is no need to log the changes to it.
5121
 
    
5122
 
    This needs to be done before external_lock
5123
 
  */
5124
 
  error= ha_enable_transaction(thd, false);
5125
 
  if (error)
5126
 
    return(-1);
5127
 
  
5128
 
  if (!(copy= new Copy_field[to->s->fields]))
5129
 
    return(-1);                         /* purecov: inspected */
5130
 
 
5131
 
  if (to->file->ha_external_lock(thd, F_WRLCK))
5132
 
    return(-1);
5133
 
 
5134
 
  /* We need external lock before we can disable/enable keys */
5135
 
  alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5136
 
 
5137
 
  /* We can abort alter table for any table type */
5138
 
  thd->abort_on_warning= !ignore;
5139
 
 
5140
 
  from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5141
 
  to->file->ha_start_bulk_insert(from->file->stats.records);
5142
 
 
5143
 
  save_sql_mode= thd->variables.sql_mode;
5144
 
 
5145
 
  List_iterator<Create_field> it(create);
5146
 
  Create_field *def;
5147
 
  copy_end=copy;
5148
 
  for (Field **ptr=to->field ; *ptr ; ptr++)
5149
 
  {
5150
 
    def=it++;
5151
 
    if (def->field)
5152
 
    {
5153
 
      if (*ptr == to->next_number_field)
5154
 
      {
5155
 
        auto_increment_field_copied= true;
5156
 
        /*
5157
 
          If we are going to copy contents of one auto_increment column to
5158
 
          another auto_increment column it is sensible to preserve zeroes.
5159
 
          This condition also covers case when we are don't actually alter
5160
 
          auto_increment column.
5161
 
        */
5162
 
        if (def->field == from->found_next_number_field)
5163
 
          thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
5164
 
      }
5165
 
      (copy_end++)->set(*ptr,def->field,0);
5166
 
    }
5167
 
 
5168
 
  }
5169
 
 
5170
 
  found_count=delete_count=0;
5171
 
 
5172
 
  if (order)
5173
 
  {
5174
 
    if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
5175
 
    {
5176
 
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
5177
 
      snprintf(warn_buff, sizeof(warn_buff), 
5178
 
               "ORDER BY ignored as there is a user-defined clustered index"
5179
 
               " in the table '%-.192s'", from->s->table_name.str);
5180
 
      push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5181
 
                   warn_buff);
5182
 
    }
5183
 
    else
5184
 
    {
5185
 
      from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5186
 
                                                MYF(MY_FAE | MY_ZEROFILL));
5187
 
      memset(&tables, 0, sizeof(tables));
5188
 
      tables.table= from;
5189
 
      tables.alias= tables.table_name= from->s->table_name.str;
5190
 
      tables.db= from->s->db.str;
5191
 
      error= 1;
5192
 
 
5193
 
      if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5194
 
          setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5195
 
                      &tables, fields, all_fields, order) ||
5196
 
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5197
 
          (from->sort.found_records= filesort(thd, from, sortorder, length,
5198
 
                                              (SQL_SELECT *) 0, HA_POS_ERROR,
5199
 
                                              1, &examined_rows)) ==
5200
 
          HA_POS_ERROR)
5201
 
        goto err;
5202
 
    }
5203
 
  };
5204
 
 
5205
 
  /* Tell handler that we have values for all columns in the to table */
5206
 
  to->use_all_columns();
5207
 
  init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5208
 
  if (ignore)
5209
 
    to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5210
 
  thd->row_count= 0;
5211
 
  restore_record(to, s->default_values);        // Create empty record
5212
 
  while (!(error=info.read_record(&info)))
5213
 
  {
5214
 
    if (thd->killed)
5215
 
    {
5216
 
      thd->send_kill_message();
5217
 
      error= 1;
5218
 
      break;
5219
 
    }
5220
 
    thd->row_count++;
5221
 
    /* Return error if source table isn't empty. */
5222
 
    if (error_if_not_empty)
5223
 
    {
5224
 
      error= 1;
5225
 
      break;
5226
 
    }
5227
 
    if (to->next_number_field)
5228
 
    {
5229
 
      if (auto_increment_field_copied)
5230
 
        to->auto_increment_field_not_null= true;
5231
 
      else
5232
 
        to->next_number_field->reset();
5233
 
    }
5234
 
    
5235
 
    for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5236
 
    {
5237
 
      copy_ptr->do_copy(copy_ptr);
5238
 
    }
5239
 
    prev_insert_id= to->file->next_insert_id;
5240
 
    error=to->file->ha_write_row(to->record[0]);
5241
 
    to->auto_increment_field_not_null= false;
5242
 
    if (error)
5243
 
    {
5244
 
      if (!ignore ||
5245
 
          to->file->is_fatal_error(error, HA_CHECK_DUP))
5246
 
      {
5247
 
         if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5248
 
         {
5249
 
           uint key_nr= to->file->get_dup_key(error);
5250
 
           if ((int) key_nr >= 0)
5251
 
           {
5252
 
             const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5253
 
             if (key_nr == 0 &&
5254
 
                 (to->key_info[0].key_part[0].field->flags &
5255
 
                  AUTO_INCREMENT_FLAG))
5256
 
               err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5257
 
             to->file->print_keydup_error(key_nr, err_msg);
5258
 
             break;
5259
 
           }
5260
 
         }
5261
 
 
5262
 
        to->file->print_error(error,MYF(0));
5263
 
        break;
5264
 
      }
5265
 
      to->file->restore_auto_increment(prev_insert_id);
5266
 
      delete_count++;
5267
 
    }
5268
 
    else
5269
 
      found_count++;
5270
 
  }
5271
 
  end_read_record(&info);
5272
 
  free_io_cache(from);
5273
 
  delete [] copy;                               // This is never 0
5274
 
 
5275
 
  if (to->file->ha_end_bulk_insert() && error <= 0)
5276
 
  {
5277
 
    to->file->print_error(my_errno,MYF(0));
5278
 
    error=1;
5279
 
  }
5280
 
  to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5281
 
 
5282
 
  if (ha_enable_transaction(thd, true))
5283
 
  {
5284
 
    error= 1;
5285
 
    goto err;
5286
 
  }
5287
 
 
5288
 
  /*
5289
 
    Ensure that the new table is saved properly to disk so that we
5290
 
    can do a rename
5291
 
  */
5292
 
  if (ha_autocommit_or_rollback(thd, 0))
5293
 
    error=1;
5294
 
  if (end_active_trans(thd))
5295
 
    error=1;
5296
 
 
5297
 
 err:
5298
 
  thd->variables.sql_mode= save_sql_mode;
5299
 
  thd->abort_on_warning= 0;
5300
 
  free_io_cache(from);
5301
 
  *copied= found_count;
5302
 
  *deleted=delete_count;
5303
 
  to->file->ha_release_auto_increment();
5304
 
  if (to->file->ha_external_lock(thd,F_UNLCK))
5305
 
    error=1;
5306
 
  return(error > 0 ? -1 : 0);
5307
 
}
5308
 
 
5309
 
 
5310
 
/*
5311
 
  Recreates tables by calling mysql_alter_table().
 
2624
                                &Cursor::ha_check));
 
2625
}
 
2626
 
 
2627
/*
 
2628
  Recreates tables by calling drizzled::alter_table().
5312
2629
 
5313
2630
  SYNOPSIS
5314
2631
    mysql_recreate_table()
5315
 
    thd                 Thread handler
 
2632
    session                     Thread Cursor
5316
2633
    tables              Tables to recreate
5317
2634
 
5318
2635
 RETURN
5319
 
    Like mysql_alter_table().
 
2636
    Like drizzled::alter_table().
5320
2637
*/
5321
 
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
 
2638
bool mysql_recreate_table(Session *session, TableList *table_list)
5322
2639
{
5323
2640
  HA_CREATE_INFO create_info;
5324
 
  Alter_info alter_info;
 
2641
  AlterInfo alter_info;
 
2642
  message::Table table_proto;
5325
2643
 
5326
2644
  assert(!table_list->next_global);
5327
2645
  /*
5334
2652
  create_info.row_type=ROW_TYPE_NOT_USED;
5335
2653
  create_info.default_table_charset=default_charset_info;
5336
2654
  /* Force alter table to recreate table */
5337
 
  alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5338
 
  return(mysql_alter_table(thd, NullS, NullS, &create_info,
5339
 
                                table_list, &alter_info, 0,
5340
 
                                (ORDER *) 0, 0));
 
2655
  alter_info.flags.set(ALTER_CHANGE_COLUMN);
 
2656
  alter_info.flags.set(ALTER_RECREATE);
 
2657
  return(alter_table(session, NULL, NULL, &create_info, &table_proto,
 
2658
                     table_list, &alter_info, 0,
 
2659
                     (order_st *) 0, 0));
5341
2660
}
5342
2661
 
5343
2662
 
5344
 
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
 
2663
bool mysql_checksum_table(Session *session, TableList *tables,
5345
2664
                          HA_CHECK_OPT *check_opt)
5346
2665
{
5347
 
  TABLE_LIST *table;
 
2666
  TableList *table;
5348
2667
  List<Item> field_list;
5349
2668
  Item *item;
5350
 
  Protocol *protocol= thd->protocol;
5351
2669
 
5352
2670
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5353
2671
  item->maybe_null= 1;
5354
2672
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5355
2673
                                          MY_INT64_NUM_DECIMAL_DIGITS));
5356
2674
  item->maybe_null= 1;
5357
 
  if (protocol->send_fields(&field_list,
5358
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
5359
 
    return(true);
 
2675
  if (session->client->sendFields(&field_list))
 
2676
    return true;
5360
2677
 
5361
2678
  /* Open one table after the other to keep lock time as short as possible. */
5362
2679
  for (table= tables; table; table= table->next_local)
5363
2680
  {
5364
2681
    char table_name[NAME_LEN*2+2];
5365
 
    TABLE *t;
5366
 
 
5367
 
    strxmov(table_name, table->db ,".", table->table_name, NullS);
5368
 
 
5369
 
    t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5370
 
    thd->clear_error();                 // these errors shouldn't get client
5371
 
 
5372
 
    protocol->prepare_for_resend();
5373
 
    protocol->store(table_name, system_charset_info);
 
2682
    Table *t;
 
2683
 
 
2684
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2685
 
 
2686
    t= table->table= session->openTableLock(table, TL_READ);
 
2687
    session->clear_error();                     // these errors shouldn't get client
 
2688
 
 
2689
    session->client->store(table_name);
5374
2690
 
5375
2691
    if (!t)
5376
2692
    {
5377
2693
      /* Table didn't exist */
5378
 
      protocol->store_null();
5379
 
      thd->clear_error();
 
2694
      session->client->store();
 
2695
      session->clear_error();
5380
2696
    }
5381
2697
    else
5382
2698
    {
5383
 
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
 
2699
      if (t->cursor->ha_table_flags() & HA_HAS_CHECKSUM &&
5384
2700
          !(check_opt->flags & T_EXTEND))
5385
 
        protocol->store((uint64_t)t->file->checksum());
5386
 
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
 
2701
        session->client->store((uint64_t)t->cursor->checksum());
 
2702
      else if (!(t->cursor->ha_table_flags() & HA_HAS_CHECKSUM) &&
5387
2703
               (check_opt->flags & T_QUICK))
5388
 
        protocol->store_null();
 
2704
        session->client->store();
5389
2705
      else
5390
2706
      {
5391
2707
        /* calculating table's checksum */
5392
2708
        ha_checksum crc= 0;
5393
 
        uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2709
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
5394
2710
 
5395
2711
        t->use_all_columns();
5396
2712
 
5397
 
        if (t->file->ha_rnd_init(1))
5398
 
          protocol->store_null();
 
2713
        if (t->cursor->ha_rnd_init(1))
 
2714
          session->client->store();
5399
2715
        else
5400
2716
        {
5401
2717
          for (;;)
5402
2718
          {
5403
2719
            ha_checksum row_crc= 0;
5404
 
            int error= t->file->rnd_next(t->record[0]);
 
2720
            int error= t->cursor->rnd_next(t->record[0]);
5405
2721
            if (unlikely(error))
5406
2722
            {
5407
2723
              if (error == HA_ERR_RECORD_DELETED)
5418
2734
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5419
2735
            }
5420
2736
 
5421
 
            for (uint i= 0; i < t->s->fields; i++ )
 
2737
            for (uint32_t i= 0; i < t->s->fields; i++ )
5422
2738
            {
5423
2739
              Field *f= t->field[i];
5424
2740
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5426
2742
              {
5427
2743
                String tmp;
5428
2744
                f->val_str(&tmp);
5429
 
                row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
 
2745
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
5430
2746
              }
5431
2747
              else
5432
2748
                row_crc= my_checksum(row_crc, f->ptr,
5435
2751
 
5436
2752
            crc+= row_crc;
5437
2753
          }
5438
 
          protocol->store((uint64_t)crc);
5439
 
          t->file->ha_rnd_end();
 
2754
          session->client->store((uint64_t)crc);
 
2755
          t->cursor->ha_rnd_end();
5440
2756
        }
5441
2757
      }
5442
 
      thd->clear_error();
5443
 
      close_thread_tables(thd);
 
2758
      session->clear_error();
 
2759
      session->close_thread_tables();
5444
2760
      table->table=0;                           // For query cache
5445
2761
    }
5446
 
    if (protocol->write())
 
2762
    if (session->client->flush())
5447
2763
      goto err;
5448
2764
  }
5449
2765
 
5450
 
  my_eof(thd);
 
2766
  session->my_eof();
5451
2767
  return(false);
5452
2768
 
5453
2769
 err:
5454
 
  close_thread_tables(thd);                     // Shouldn't be needed
 
2770
  session->close_thread_tables();                       // Shouldn't be needed
5455
2771
  if (table)
5456
2772
    table->table=0;
5457
2773
  return(true);
5458
2774
}
5459
2775
 
5460
 
static bool check_engine(THD *thd, const char *table_name,
 
2776
bool check_engine(Session *session, const char *table_name,
5461
2777
                         HA_CREATE_INFO *create_info)
5462
2778
{
5463
 
  handlerton **new_engine= &create_info->db_type;
5464
 
  handlerton *req_engine= *new_engine;
5465
 
  bool no_substitution= 1;
5466
 
  if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5467
 
                                  no_substitution, 1)))
 
2779
  plugin::StorageEngine **new_engine= &create_info->db_type;
 
2780
  plugin::StorageEngine *req_engine= *new_engine;
 
2781
  if (!req_engine->is_enabled())
 
2782
  {
 
2783
    string engine_name= req_engine->getName();
 
2784
    my_error(ER_FEATURE_DISABLED,MYF(0),
 
2785
             engine_name.c_str(), engine_name.c_str());
 
2786
             
5468
2787
    return true;
 
2788
  }
5469
2789
 
5470
2790
  if (req_engine && req_engine != *new_engine)
5471
2791
  {
5472
 
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2792
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5473
2793
                       ER_WARN_USING_OTHER_HANDLER,
5474
2794
                       ER(ER_WARN_USING_OTHER_HANDLER),
5475
 
                       ha_resolve_storage_engine_name(*new_engine),
 
2795
                       plugin::StorageEngine::resolveName(*new_engine).c_str(),
5476
2796
                       table_name);
5477
2797
  }
5478
2798
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5479
 
      ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
 
2799
      (*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
5480
2800
  {
5481
2801
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5482
2802
    {
5483
2803
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5484
 
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
 
2804
               plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2805
               "TEMPORARY");
5485
2806
      *new_engine= 0;
5486
2807
      return true;
5487
2808
    }
5488
 
    *new_engine= myisam_hton;
5489
 
  }
 
2809
    *new_engine= myisam_engine;
 
2810
  }
 
2811
  if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2812
     && (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
 
2813
  {
 
2814
    my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
 
2815
             plugin::StorageEngine::resolveName(*new_engine).c_str(),
 
2816
             "non-TEMPORARY");
 
2817
    *new_engine= 0;
 
2818
    return true;
 
2819
  }
 
2820
 
5490
2821
  return false;
5491
2822
}