~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

pandora-build v0.100 - Fixes several bugs found by cb1kenobi. Add several thoughts from folks at LCA.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
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";
 
18
#include "config.h"
 
19
#include <plugin/myisam/myisam.h>
 
20
#include <drizzled/show.h>
 
21
#include <drizzled/error.h>
 
22
#include <drizzled/gettext.h>
 
23
#include <drizzled/data_home.h>
 
24
#include <drizzled/sql_parse.h>
 
25
#include <drizzled/my_hash.h>
 
26
#include <drizzled/sql_lex.h>
 
27
#include <drizzled/session.h>
 
28
#include <drizzled/sql_base.h>
 
29
#include "drizzled/strfunc.h"
 
30
#include <drizzled/db.h>
 
31
#include <drizzled/lock.h>
 
32
#include <drizzled/unireg.h>
 
33
#include <drizzled/item/int.h>
 
34
#include <drizzled/item/empty_string.h>
 
35
#include <drizzled/replication_services.h>
 
36
#include <drizzled/table_proto.h>
 
37
#include <drizzled/plugin/client.h>
 
38
#include <drizzled/table_identifier.h>
 
39
#include "drizzled/internal/m_string.h"
 
40
#include "drizzled/global_charset_info.h"
 
41
#include "drizzled/charset.h"
 
42
 
 
43
 
 
44
#include "drizzled/statement/alter_table.h"
 
45
#include "drizzled/plugin/info_schema_table.h"
 
46
#include "drizzled/sql_table.h"
 
47
#include "drizzled/pthread_globals.h"
 
48
 
 
49
#include <algorithm>
 
50
#include <sstream>
 
51
 
 
52
using namespace std;
 
53
using namespace drizzled;
 
54
 
 
55
extern pid_t current_pid;
 
56
 
 
57
static const char hexchars[]= "0123456789abcdef";
 
58
bool is_primary_key(KEY *key_info)
 
59
{
 
60
  static const char * primary_key_name="PRIMARY";
 
61
  return (strcmp(key_info->name, primary_key_name)==0);
 
62
}
 
63
 
 
64
const char* is_primary_key_name(const char* key_name)
 
65
{
 
66
  static const char * primary_key_name="PRIMARY";
 
67
  if (strcmp(key_name, primary_key_name)==0)
 
68
    return key_name;
 
69
  else
 
70
    return NULL;
 
71
}
26
72
 
27
73
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
28
74
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);
 
75
 
 
76
static bool prepare_blob_field(Session *session, CreateField *sql_field);
 
77
 
 
78
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
 
79
{
 
80
  /*
 
81
    If the table character set was not given explicitly,
 
82
    let's fetch the database default character set and
 
83
    apply it to the table.
 
84
  */
 
85
  if (create_info->default_table_charset == NULL)
 
86
    create_info->default_table_charset= get_default_db_collation(db);
 
87
}
49
88
 
50
89
/*
51
 
  Translate a file name to a table name (WL #1324).
 
90
  Translate a cursor name to a table name (WL #1324).
52
91
 
53
92
  SYNOPSIS
54
93
    filename_to_tablename()
55
 
      from                      The file name in my_charset_filename.
56
 
      to                OUT     The table name in system_charset_info.
 
94
      from                      The cursor name
 
95
      to                OUT     The table name
57
96
      to_length                 The size of the table name buffer.
58
97
 
59
98
  RETURN
60
99
    Table name length.
61
100
*/
62
 
uint filename_to_tablename(const char *from, char *to, uint to_length)
 
101
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
63
102
{
64
 
  uint errors;
65
 
  uint res;
 
103
  uint32_t length= 0;
66
104
 
67
 
  if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length))
 
105
  if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
68
106
  {
69
107
    /* Temporary table name. */
70
 
    res= (stpncpy(to, from, to_length) - to);
 
108
    length= strlen(strncpy(to, from, to_length));
71
109
  }
72
110
  else
73
111
  {
74
 
    res= strconvert(&my_charset_filename, from,
75
 
                    system_charset_info,  to, to_length, &errors);
76
 
    if (errors) // Old 5.0 name
 
112
    for (; *from  && length < to_length; length++, from++)
77
113
    {
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
 
    }
 
114
      if (*from != '@')
 
115
      {
 
116
        to[length]= *from;
 
117
        continue;
 
118
      }
 
119
      /* We've found an escaped char - skip the @ */
 
120
      from++;
 
121
      to[length]= 0;
 
122
      /* There will be a two-position hex-char version of the char */
 
123
      for (int x=1; x >= 0; x--)
 
124
      {
 
125
        if (*from >= '0' && *from <= '9')
 
126
          to[length] += ((*from++ - '0') << (4 * x));
 
127
        else if (*from >= 'a' && *from <= 'f')
 
128
          to[length] += ((*from++ - 'a' + 10) << (4 * x));
 
129
      }
 
130
      /* Backup because we advanced extra in the inner loop */
 
131
      from--;
 
132
    } 
86
133
  }
87
134
 
88
 
  return(res);
 
135
  return length;
89
136
}
90
137
 
91
138
 
92
139
/*
93
 
  Translate a table name to a file name (WL #1324).
 
140
  Translate a table name to a cursor name (WL #1324).
94
141
 
95
142
  SYNOPSIS
96
143
    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.
 
144
      from                      The table name
 
145
      to                OUT     The cursor name
 
146
      to_length                 The size of the cursor name buffer.
100
147
 
101
148
  RETURN
102
 
    File name length.
 
149
    true if errors happen. false on success.
103
150
*/
104
 
 
105
 
uint tablename_to_filename(const char *from, char *to, uint to_length)
 
151
bool tablename_to_filename(const char *from, char *to, size_t to_length)
106
152
{
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);
 
153
  
 
154
  size_t length= 0;
 
155
  for (; *from  && length < to_length; length++, from++)
 
156
  {
 
157
    if ((*from >= '0' && *from <= '9') ||
 
158
        (*from >= 'A' && *from <= 'Z') ||
 
159
        (*from >= 'a' && *from <= 'z') ||
 
160
/* OSX defines an extra set of high-bit and multi-byte characters
 
161
   that cannot be used on the filesystem. Instead of trying to sort
 
162
   those out, we'll just escape encode all high-bit-set chars on OSX.
 
163
   It won't really hurt anything - it'll just make some filenames ugly. */
 
164
#if !defined(TARGET_OS_OSX)
 
165
        ((unsigned char)*from >= 128) ||
 
166
#endif
 
167
        (*from == '_') ||
 
168
        (*from == ' ') ||
 
169
        (*from == '-'))
 
170
    {
 
171
      to[length]= *from;
 
172
      continue;
 
173
    }
 
174
   
 
175
    if (length + 3 >= to_length)
 
176
      return true;
 
177
 
 
178
    /* We need to escape this char in a way that can be reversed */
 
179
    to[length++]= '@';
 
180
    to[length++]= hexchars[(*from >> 4) & 15];
 
181
    to[length]= hexchars[(*from) & 15];
 
182
  }
 
183
 
116
184
  if (check_if_legal_tablename(to) &&
117
185
      length + 4 < to_length)
118
186
  {
119
187
    memcpy(to + length, "@@@", 4);
120
188
    length+= 3;
121
189
  }
122
 
  return(length);
 
190
  return false;
123
191
}
124
192
 
125
193
 
126
194
/*
127
 
  Creates path to a file: mysql_data_dir/db/table.ext
 
195
  Creates path to a cursor: drizzle_data_dir/db/table.ext
128
196
 
129
197
  SYNOPSIS
130
198
   build_table_filename()
131
 
     buff                       Where to write result in my_charset_filename.
 
199
     buff                       Where to write result
132
200
                                This may be the same as table_name.
133
201
     bufflen                    buff size
134
 
     db                         Database name in system_charset_info.
135
 
     table_name                 Table name in system_charset_info.
 
202
     db                         Database name
 
203
     table_name                 Table name
136
204
     ext                        File extension.
137
 
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
 
205
     flags                      FN_FROM_IS_TMP or FN_TO_IS_TMP
138
206
                                table_name is temporary, do not change.
139
207
 
140
208
  NOTES
141
209
 
142
210
    Uses database and table name, and extension to create
143
 
    a file name in mysql_data_dir. Database and table
 
211
    a cursor name in drizzle_data_dir. Database and table
144
212
    names are converted from system_charset_info into "fscs".
145
213
    Unless flags indicate a temporary table name.
146
214
    'db' is always converted.
147
215
    'ext' is not converted.
148
216
 
149
 
    The conversion suppression is required for ALTER TABLE. This
 
217
    The conversion suppression is required for ALTER Table. This
150
218
    statement creates intermediate tables. These are regular
151
219
    (non-temporary) tables with a temporary name. Their path names must
152
220
    be derivable from the table name. So we cannot use
153
221
    build_tmptable_filename() for them.
154
222
 
155
223
  RETURN
156
 
    path length
 
224
    path length on success, 0 on failure
157
225
*/
158
226
 
159
 
uint build_table_filename(char *buff, size_t bufflen, const char *db,
160
 
                          const char *table_name, const char *ext, uint flags)
 
227
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
161
228
{
162
229
  char dbbuff[FN_REFLEN];
163
230
  char tbbuff[FN_REFLEN];
 
231
  bool conversion_error= false;
164
232
 
165
 
  if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
166
 
    stpncpy(tbbuff, table_name, sizeof(tbbuff));
 
233
  memset(tbbuff, 0, sizeof(tbbuff));
 
234
  if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
 
235
    strncpy(tbbuff, table_name, sizeof(tbbuff));
167
236
  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);
 
237
  {
 
238
    conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
 
239
    if (conversion_error)
 
240
    {
 
241
      errmsg_printf(ERRMSG_LVL_ERROR,
 
242
                    _("Table name cannot be encoded and fit within filesystem "
 
243
                      "name length restrictions."));
 
244
      return 0;
 
245
    }
 
246
  }
 
247
  memset(dbbuff, 0, sizeof(dbbuff));
 
248
  conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
 
249
  if (conversion_error)
 
250
  {
 
251
    errmsg_printf(ERRMSG_LVL_ERROR,
 
252
                  _("Schema name cannot be encoded and fit within filesystem "
 
253
                    "name length restrictions."));
 
254
    return 0;
 
255
  }
 
256
   
 
257
 
175
258
  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);
 
259
  string table_path(drizzle_data_home);
 
260
  int without_rootdir= table_path.length()-rootdir_len;
 
261
 
 
262
  /* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
 
263
  if (without_rootdir >= 0)
 
264
  {
 
265
    const char *tmp= table_path.c_str()+without_rootdir;
 
266
    if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
 
267
      table_path.append(FN_ROOTDIR);
 
268
  }
 
269
 
 
270
  table_path.append(dbbuff);
 
271
  table_path.append(FN_ROOTDIR);
 
272
  table_path.append(tbbuff);
 
273
 
 
274
  if (bufflen < table_path.length())
 
275
    return 0;
 
276
 
 
277
  strcpy(buff, table_path.c_str());
 
278
 
 
279
  return table_path.length();
187
280
}
188
281
 
189
282
 
190
283
/*
191
 
  Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
 
284
  Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
192
285
 
193
286
  SYNOPSIS
194
287
   build_tmptable_filename()
195
 
     thd                        The thread handle.
196
 
     buff                       Where to write result in my_charset_filename.
 
288
     session                    The thread handle.
 
289
     buff                       Where to write result
197
290
     bufflen                    buff size
198
291
 
199
292
  NOTES
200
293
 
201
294
    Uses current_pid, thread_id, and tmp_table counter to create
202
 
    a file name in mysql_tmpdir.
 
295
    a cursor name in drizzle_tmpdir.
203
296
 
204
297
  RETURN
205
 
    path length
 
298
    path length on success, 0 on failure
206
299
*/
207
300
 
208
 
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
 
301
size_t build_tmptable_filename(char *buff, size_t bufflen)
209
302
{
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);
 
303
  size_t length;
 
304
  ostringstream path_str, post_tmpdir_str;
 
305
  string tmp;
 
306
 
 
307
  Session *session= current_session;
 
308
 
 
309
  path_str << drizzle_tmpdir;
 
310
  post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
 
311
  post_tmpdir_str << session->thread_id << session->tmp_table++;
 
312
  tmp= post_tmpdir_str.str();
 
313
 
 
314
  transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
 
315
 
 
316
  path_str << tmp;
 
317
 
 
318
  if (bufflen < path_str.str().length())
 
319
    length= 0;
 
320
  else
 
321
    length= unpack_filename(buff, path_str.str().c_str());
 
322
 
 
323
  return length;
224
324
}
225
325
 
226
326
/*
227
327
  SYNOPSIS
228
328
    write_bin_log()
229
 
    thd                           Thread object
230
 
    clear_error                   is clear_error to be called
 
329
    session                           Thread object
231
330
    query                         Query to log
232
331
    query_length                  Length of query
233
332
 
236
335
 
237
336
  DESCRIPTION
238
337
    Write the binlog if open, routine used in multiple places in this
239
 
    file
 
338
    cursor
240
339
*/
241
340
 
242
 
void write_bin_log(THD *thd, bool clear_error,
243
 
                   char const *query, ulong query_length)
 
341
void write_bin_log(Session *session,
 
342
                   char const *query, size_t query_length)
244
343
{
245
 
  if (mysql_bin_log.is_open())
246
 
  {
247
 
    if (clear_error)
248
 
      thd->clear_error();
249
 
    thd->binlog_query(THD::STMT_QUERY_TYPE,
250
 
                      query, query_length, false, false);
251
 
  }
 
344
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
345
  replication_services.rawStatement(session, query, query_length);
252
346
}
253
347
 
254
348
 
255
 
/*
256
 
 delete (drop) tables.
257
 
 
258
 
  SYNOPSIS
259
 
   mysql_rm_table()
260
 
   thd                  Thread handle
261
 
   tables               List of tables to delete
262
 
   if_exists            If 1, don't give error if one table doesn't exists
263
 
 
264
 
  NOTES
265
 
    Will delete all tables that can be deleted and give a compact error
266
 
    messages for tables that could not be deleted.
267
 
    If a table is in use, we will wait for all users to free the table
268
 
    before dropping it
269
 
 
270
 
    Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
271
 
    not if under LOCK TABLES.
272
 
 
273
 
  RETURN
274
 
    false OK.  In this case ok packet is sent to user
275
 
    true  Error
276
 
 
277
 
*/
278
 
 
279
 
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, bool drop_temporary)
 
349
/* Should should be refactored to go away */
 
350
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
280
351
{
281
 
  bool error, need_start_waiting= false;
282
 
 
283
 
  if (tables && tables->schema_table)
284
 
  {
285
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
286
 
    return(true);
287
 
  }
288
 
 
289
 
  /* mark for close and remove all cached entries */
290
 
 
291
 
  if (!drop_temporary)
292
 
  {
293
 
    if (!thd->locked_tables &&
294
 
        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
295
 
      return(true);
296
 
  }
297
 
 
298
 
  /*
299
 
    Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
300
 
    LOCK_open during wait_if_global_read_lock(), other threads could not
301
 
    close their tables. This would make a pretty deadlock.
302
 
  */
303
 
  error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
304
 
 
305
 
  if (need_start_waiting)
306
 
    start_waiting_global_read_lock(thd);
307
 
 
308
 
  if (error)
309
 
    return(true);
310
 
  my_ok(thd);
311
 
  return(false);
 
352
  ReplicationServices &replication_services= ReplicationServices::singleton();
 
353
  string built_query;
 
354
 
 
355
  if (if_exists)
 
356
    built_query.append("DROP TABLE IF EXISTS ");
 
357
  else
 
358
    built_query.append("DROP TABLE ");
 
359
 
 
360
  built_query.append("`");
 
361
  if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
 
362
  {
 
363
    built_query.append(db_name);
 
364
    built_query.append("`.`");
 
365
  }
 
366
 
 
367
  built_query.append(table_name);
 
368
  built_query.append("`");
 
369
  replication_services.rawStatement(session, built_query.c_str(), built_query.length());
312
370
}
313
371
 
314
372
/*
316
374
 
317
375
  SYNOPSIS
318
376
    mysql_rm_table_part2()
319
 
    thd                 Thread handler
 
377
    session                     Thread Cursor
320
378
    tables              Tables to drop
321
379
    if_exists           If set, don't give an error if table doesn't exists.
322
380
                        In this case we give an warning of level 'NOTE'
323
381
    drop_temporary      Only drop temporary tables
324
 
    drop_view           Allow to delete VIEW .frm
325
 
    dont_log_query      Don't write query to log files. This will also not
326
 
                        generate warnings if the handler files doesn't exists  
327
382
 
328
383
  TODO:
329
384
    When logging to the binary log, we should log
341
396
   -1   Thread was killed
342
397
*/
343
398
 
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)
 
399
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
400
                         bool drop_temporary)
347
401
{
348
 
  TABLE_LIST *table;
349
 
  char path[FN_REFLEN], *alias;
350
 
  uint path_length;
 
402
  TableList *table;
 
403
  char path[FN_REFLEN];
 
404
  uint32_t path_length= 0;
351
405
  String wrong_tables;
352
406
  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);
 
407
  bool foreign_key_error= false;
 
408
 
 
409
  pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
369
410
 
370
411
  /*
371
412
    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
 
413
    .frm cursor to find if the table is a normal table (not view) and what
373
414
    engine to use.
374
415
  */
375
416
 
376
417
  for (table= tables; table; table= table->next_local)
377
418
  {
378
 
    TABLE_SHARE *share;
 
419
    TableShare *share;
379
420
    table->db_type= NULL;
380
 
    if ((share= get_cached_table_share(table->db, table->table_name)))
 
421
    if ((share= TableShare::getShare(table->db, table->table_name)))
381
422
      table->db_type= share->db_type();
382
423
  }
383
424
 
384
 
  if (!drop_temporary && lock_table_names_exclusively(thd, tables))
 
425
  if (!drop_temporary && lock_table_names_exclusively(session, tables))
385
426
  {
386
427
    pthread_mutex_unlock(&LOCK_open);
387
 
    return(1);
 
428
    return 1;
388
429
  }
389
430
 
390
431
  /* Don't give warnings for not found errors, as we already generate notes */
391
 
  thd->no_warnings_for_error= 1;
 
432
  session->no_warnings_for_error= 1;
392
433
 
393
434
  for (table= tables; table; table= table->next_local)
394
435
  {
395
436
    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);
 
437
    plugin::StorageEngine *table_type;
 
438
 
 
439
    error= session->drop_temporary_table(table);
401
440
 
402
441
    switch (error) {
403
442
    case  0:
404
443
      // removed temporary table
405
 
      tmp_table_deleted= 1;
406
444
      continue;
407
445
    case -1:
408
 
      assert(thd->in_sub_stmt);
409
446
      error= 1;
410
447
      goto err_with_placeholders;
411
448
    default:
413
450
      error= 0;
414
451
    }
415
452
 
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
453
    table_type= table->db_type;
441
 
    if (!drop_temporary)
 
454
    if (drop_temporary == false)
442
455
    {
443
 
      TABLE *locked_table;
444
 
      abort_locked_tables(thd, db, table->table_name);
445
 
      remove_table_from_cache(thd, db, table->table_name,
 
456
      Table *locked_table;
 
457
      abort_locked_tables(session, db, table->table_name);
 
458
      remove_table_from_cache(session, db, table->table_name,
446
459
                              RTFC_WAIT_OTHER_THREAD_FLAG |
447
460
                              RTFC_CHECK_KILLED_FLAG);
448
461
      /*
449
462
        If the table was used in lock tables, remember it so that
450
463
        unlock_table_names can free it
451
464
      */
452
 
      if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
 
465
      if ((locked_table= drop_locked_tables(session, db, table->table_name)))
453
466
        table->table= locked_table;
454
467
 
455
 
      if (thd->killed)
 
468
      if (session->killed)
456
469
      {
457
470
        error= -1;
458
471
        goto err_with_placeholders;
459
472
      }
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);
 
473
      /* remove .frm cursor and engine files */
 
474
      path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
465
475
    }
 
476
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
 
477
 
466
478
    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)))
 
479
        ((table_type == NULL
 
480
          && (plugin::StorageEngine::getTableDefinition(*session,
 
481
                                                        identifier) != EEXIST))))
469
482
    {
470
483
      // Table was not found on disk and table can't be created from engine
471
484
      if (if_exists)
472
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
485
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
473
486
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
474
487
                            table->table_name);
475
488
      else
477
490
    }
478
491
    else
479
492
    {
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))
 
493
      error= plugin::StorageEngine::dropTable(*session,
 
494
                                              identifier,
 
495
                                              true);
 
496
 
 
497
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
492
498
      {
493
499
        error= 0;
494
 
        thd->clear_error();
 
500
        session->clear_error();
495
501
      }
 
502
 
496
503
      if (error == HA_ERR_ROW_IS_REFERENCED)
497
504
      {
498
505
        /* 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;
 
506
        foreign_key_error= true;
512
507
      }
513
508
    }
 
509
 
 
510
    if (error == 0 || (if_exists && foreign_key_error == false))
 
511
        write_bin_log_drop_table(session, if_exists, db, table->table_name);
 
512
 
514
513
    if (error)
515
514
    {
516
515
      if (wrong_tables.length())
523
522
    on the table name.
524
523
  */
525
524
  pthread_mutex_unlock(&LOCK_open);
526
 
  thd->thread_specific_used|= tmp_table_deleted;
527
525
  error= 0;
528
526
  if (wrong_tables.length())
529
527
  {
537
535
    error= 1;
538
536
  }
539
537
 
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);
 
538
  pthread_mutex_lock(&LOCK_open); /* final bit in rm table lock */
587
539
err_with_placeholders:
588
 
  unlock_table_names(thd, tables, (TABLE_LIST*) 0);
 
540
  unlock_table_names(tables, NULL);
589
541
  pthread_mutex_unlock(&LOCK_open);
590
 
  thd->no_warnings_for_error= 0;
 
542
  session->no_warnings_for_error= 0;
 
543
 
591
544
  return(error);
592
545
}
593
546
 
597
550
 
598
551
  SYNOPSIS
599
552
    quick_rm_table()
600
 
      base                      The handlerton handle.
 
553
      base                      The plugin::StorageEngine handle.
601
554
      db                        The database name.
602
555
      table_name                The table name.
603
 
      flags                     flags for build_table_filename().
 
556
      is_tmp                    If the table is temp.
604
557
 
605
558
  RETURN
606
559
    0           OK
607
560
    != 0        Error
608
561
*/
609
 
 
610
 
bool quick_rm_table(handlerton *base,const char *db,
611
 
                    const char *table_name, uint flags)
 
562
bool quick_rm_table(Session& session,
 
563
                    TableIdentifier &identifier)
612
564
{
613
 
  char path[FN_REFLEN];
614
 
  bool error= 0;
615
 
 
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);
 
565
  return (plugin::StorageEngine::dropTable(session, identifier, false));
623
566
}
624
567
 
625
568
/*
638
581
static int sort_keys(KEY *a, KEY *b)
639
582
{
640
583
  ulong a_flags= a->flags, b_flags= b->flags;
641
 
  
 
584
 
642
585
  if (a_flags & HA_NOSAME)
643
586
  {
644
587
    if (!(b_flags & HA_NOSAME))
648
591
      /* Sort NOT NULL keys before other keys */
649
592
      return (a_flags & (HA_NULL_PART_KEY)) ? 1 : -1;
650
593
    }
651
 
    if (a->name == primary_key_name)
 
594
    if (is_primary_key(a))
652
595
      return -1;
653
 
    if (b->name == primary_key_name)
 
596
    if (is_primary_key(b))
654
597
      return 1;
655
598
    /* Sort keys don't containing partial segments before others */
656
599
    if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
687
630
    1             Error
688
631
*/
689
632
 
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)
 
633
static bool check_duplicates_in_interval(const char *set_or_name,
 
634
                                         const char *name, TYPELIB *typelib,
 
635
                                         const CHARSET_INFO * const cs,
 
636
                                         unsigned int *dup_val_count)
693
637
{
694
638
  TYPELIB tmp= *typelib;
695
639
  const char **cur_value= typelib->type_names;
696
640
  unsigned int *cur_length= typelib->type_lengths;
697
 
  *dup_val_count= 0;  
698
 
  
 
641
  *dup_val_count= 0;
 
642
 
699
643
  for ( ; tmp.count > 1; cur_value++, cur_length++)
700
644
  {
701
645
    tmp.type_names++;
730
674
  RETURN VALUES
731
675
    void
732
676
*/
733
 
void calculate_interval_lengths(const CHARSET_INFO * const cs, TYPELIB *interval,
734
 
                                uint32_t *max_length, uint32_t *tot_length)
 
677
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
 
678
                                       TYPELIB *interval,
 
679
                                       uint32_t *max_length,
 
680
                                       uint32_t *tot_length)
735
681
{
736
682
  const char **pos;
737
 
  uint *len;
 
683
  uint32_t *len;
738
684
  *max_length= *tot_length= 0;
739
685
  for (pos= interval->type_names, len= interval->type_lengths;
740
686
       *pos ; pos++, len++)
741
687
  {
742
 
    uint length= cs->cset->numchars(cs, *pos, *pos + *len);
 
688
    uint32_t length= cs->cset->numchars(cs, *pos, *pos + *len);
743
689
    *tot_length+= length;
744
690
    set_if_bigger(*max_length, (uint32_t)length);
745
691
  }
746
692
}
747
693
 
748
 
 
749
694
/*
750
695
  Prepare a create_table instance for packing
751
696
 
754
699
    sql_field     field to prepare for packing
755
700
    blob_columns  count for BLOBs
756
701
    timestamps    count for timestamps
757
 
    table_flags   table flags
758
702
 
759
703
  DESCRIPTION
760
 
    This function prepares a Create_field instance.
 
704
    This function prepares a CreateField instance.
761
705
    Fields such as pack_flag are valid after this call.
762
706
 
763
707
  RETURN VALUES
764
708
   0    ok
765
709
   1    Error
766
710
*/
767
 
 
768
 
int prepare_create_field(Create_field *sql_field, 
769
 
                         uint *blob_columns,
770
 
                         int *timestamps, int *timestamps_with_niladic,
771
 
                         int64_t table_flags __attribute__((unused)))
 
711
int prepare_create_field(CreateField *sql_field,
 
712
                         uint32_t *blob_columns,
 
713
                         int *timestamps,
 
714
                         int *timestamps_with_niladic)
772
715
{
773
716
  unsigned int dup_val_count;
774
717
 
780
723
 
781
724
  switch (sql_field->sql_type) {
782
725
  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;
 
726
    sql_field->pack_flag= pack_length_to_packflag(sql_field->pack_length - portable_sizeof_char_ptr);
 
727
    sql_field->length= 8; // Unireg field length
790
728
    (*blob_columns)++;
791
729
    break;
792
730
  case DRIZZLE_TYPE_VARCHAR:
793
731
    sql_field->pack_flag=0;
794
 
    if (sql_field->charset->state & MY_CS_BINSORT)
795
 
      sql_field->pack_flag|=FIELDFLAG_BINARY;
796
732
    break;
797
733
  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);
 
734
    sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length);
 
735
    if (check_duplicates_in_interval("ENUM",
 
736
                                     sql_field->field_name,
 
737
                                     sql_field->interval,
 
738
                                     sql_field->charset,
 
739
                                     &dup_val_count))
 
740
      return 1;
807
741
    break;
808
 
  case DRIZZLE_TYPE_NEWDATE:  // Rest of string types
809
 
  case DRIZZLE_TYPE_TIME:
 
742
  case DRIZZLE_TYPE_DATE:  // Rest of string types
810
743
  case DRIZZLE_TYPE_DATETIME:
811
744
  case DRIZZLE_TYPE_NULL:
812
 
    sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
 
745
    sql_field->pack_flag=f_settype((uint32_t) sql_field->sql_type);
813
746
    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));
 
747
  case DRIZZLE_TYPE_DECIMAL:
 
748
    sql_field->pack_flag= 0;
820
749
    break;
821
750
  case DRIZZLE_TYPE_TIMESTAMP:
822
751
    /* We should replace old TIMESTAMP fields with their newer analogs */
836
765
    (*timestamps)++;
837
766
    /* fall-through */
838
767
  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));
 
768
    sql_field->pack_flag=(0 |
 
769
                          f_settype((uint32_t) sql_field->sql_type));
844
770
    break;
845
771
  }
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);
 
772
  return 0;
851
773
}
852
774
 
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)
 
775
int mysql_prepare_create_table(Session *session,
 
776
                               HA_CREATE_INFO *create_info,
 
777
                               message::Table *create_proto,
 
778
                               AlterInfo *alter_info,
 
779
                               bool tmp_table,
 
780
                               uint32_t *db_options,
 
781
                               Cursor *cursor,
 
782
                               KEY **key_info_buffer,
 
783
                               uint32_t *key_count,
 
784
                               int select_field_count)
886
785
{
887
786
  const char    *key_name;
888
 
  Create_field  *sql_field,*dup_field;
 
787
  CreateField   *sql_field,*dup_field;
889
788
  uint          field,null_fields,blob_columns,max_key_length;
890
789
  ulong         record_offset= 0;
891
790
  KEY           *key_info;
893
792
  int           timestamps= 0, timestamps_with_niladic= 0;
894
793
  int           field_no,dup_no;
895
794
  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;
 
795
  List_iterator<CreateField> it(alter_info->create_list);
 
796
  List_iterator<CreateField> it2(alter_info->create_list);
 
797
  uint32_t total_uneven_bit_length= 0;
899
798
 
900
799
  select_field_pos= alter_info->create_list.elements - select_field_count;
901
800
  null_fields=blob_columns=0;
902
 
  create_info->varchar= 0;
903
 
  max_key_length= file->max_key_length();
 
801
  max_key_length= cursor->getEngine()->max_key_length();
904
802
 
905
803
  for (field_no=0; (sql_field=it++) ; field_no++)
906
804
  {
915
813
    if (!sql_field->charset)
916
814
      sql_field->charset= create_info->default_table_charset;
917
815
    /*
918
 
      table_charset is set in ALTER TABLE if we want change character set
 
816
      table_charset is set in ALTER Table if we want change character set
919
817
      for all varchar/char columns.
920
818
      But the table charset must not affect the BLOB fields, so don't
921
819
      allow to change my_charset_bin to somethig else.
925
823
 
926
824
    save_cs= sql_field->charset;
927
825
    if ((sql_field->flags & BINCMP_FLAG) &&
928
 
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
929
 
                                                    MY_CS_BINSORT,MYF(0))))
 
826
        !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, MY_CS_BINSORT)))
930
827
    {
931
828
      char tmp[64];
932
 
      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
933
 
              STRING_WITH_LEN("_bin"));
 
829
      char *tmp_pos= tmp;
 
830
      strncpy(tmp_pos, save_cs->csname, sizeof(tmp)-4);
 
831
      tmp_pos+= strlen(tmp);
 
832
      strncpy(tmp_pos, STRING_WITH_LEN("_bin"));
934
833
      my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
935
834
      return(true);
936
835
    }
939
838
      Convert the default value from client character
940
839
      set into the column character set if necessary.
941
840
    */
942
 
    if (sql_field->def && 
 
841
    if (sql_field->def &&
943
842
        save_cs != sql_field->def->collation.collation &&
944
843
        (sql_field->sql_type == DRIZZLE_TYPE_ENUM))
945
844
    {
946
845
      /*
947
 
        Starting from 5.1 we work here with a copy of Create_field
 
846
        Starting from 5.1 we work here with a copy of CreateField
948
847
        created by the caller, not with the instance that was
949
848
        originally created during parsing. It's OK to create
950
849
        a temporary item and initialize with it a member of the
981
880
          occupied memory at the same time when we free this
982
881
          sql_field -- at the end of execution.
983
882
        */
984
 
        interval= sql_field->interval= typelib(thd->mem_root,
 
883
        interval= sql_field->interval= typelib(session->mem_root,
985
884
                                               sql_field->interval_list);
 
885
 
986
886
        List_iterator<String> int_it(sql_field->interval_list);
987
887
        String conv, *tmp;
988
888
        char comma_buf[4];
989
 
        int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
990
 
                                          (uchar*) comma_buf + 
 
889
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
 
890
                                          (unsigned char*) comma_buf +
991
891
                                          sizeof(comma_buf));
992
892
        assert(comma_length > 0);
993
 
        for (uint i= 0; (tmp= int_it++); i++)
 
893
 
 
894
        for (uint32_t i= 0; (tmp= int_it++); i++)
994
895
        {
995
 
          uint lengthsp;
 
896
          uint32_t lengthsp;
996
897
          if (String::needs_conversion(tmp->length(), tmp->charset(),
997
898
                                       cs, &dummy))
998
899
          {
999
 
            uint cnv_errs;
 
900
            uint32_t cnv_errs;
1000
901
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
1001
 
            interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
 
902
            interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
1002
903
                                                  conv.length());
1003
904
            interval->type_lengths[i]= conv.length();
1004
905
          }
1007
908
          lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
1008
909
                                       interval->type_lengths[i]);
1009
910
          interval->type_lengths[i]= lengthsp;
1010
 
          ((uchar *)interval->type_names[i])[lengthsp]= '\0';
 
911
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
1011
912
        }
1012
913
        sql_field->interval_list.empty(); // Don't need interval_list anymore
1013
914
      }
1028
929
            }
1029
930
 
1030
931
            /* else, the defaults yield the correct length for NULLs. */
1031
 
          } 
 
932
          }
1032
933
          else /* not NULL */
1033
934
          {
1034
935
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
1042
943
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
1043
944
        sql_field->length= field_length;
1044
945
      }
1045
 
      set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
 
946
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
1046
947
    }
1047
948
 
1048
949
    sql_field->create_length_to_internal_length();
1049
 
    if (prepare_blob_field(thd, sql_field))
 
950
    if (prepare_blob_field(session, sql_field))
1050
951
      return(true);
1051
952
 
1052
953
    if (!(sql_field->flags & NOT_NULL_FLAG))
1088
989
          sql_field->decimals=          dup_field->decimals;
1089
990
          sql_field->create_length_to_internal_length();
1090
991
          sql_field->unireg_check=      dup_field->unireg_check;
1091
 
          /* 
 
992
          /*
1092
993
            We're making one field from two, the result field will have
1093
994
            dup_field->flags as flags. If we've incremented null_fields
1094
995
            because of sql_field->flags, decrement it back.
1119
1020
  {
1120
1021
    assert(sql_field->charset != 0);
1121
1022
 
1122
 
    if (prepare_create_field(sql_field, &blob_columns, 
1123
 
                             &timestamps, &timestamps_with_niladic,
1124
 
                             file->ha_table_flags()))
 
1023
    if (prepare_create_field(sql_field, &blob_columns,
 
1024
                             &timestamps, &timestamps_with_niladic))
1125
1025
      return(true);
1126
 
    if (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
1127
 
      create_info->varchar= true;
1128
1026
    sql_field->offset= record_offset;
1129
1027
    if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1130
1028
      auto_increment++;
1131
 
    record_offset+= sql_field->pack_length;
1132
1029
  }
1133
1030
  if (timestamps_with_niladic > 1)
1134
1031
  {
1142
1039
    return(true);
1143
1040
  }
1144
1041
  if (auto_increment &&
1145
 
      (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
 
1042
      (cursor->getEngine()->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
1146
1043
  {
1147
1044
    my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
1148
1045
               ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
1149
1046
    return(true);
1150
1047
  }
1151
1048
 
1152
 
  if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
 
1049
  if (blob_columns && (cursor->getEngine()->check_flag(HTON_BIT_NO_BLOBS)))
1153
1050
  {
1154
1051
    my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
1155
1052
               MYF(0));
1160
1057
 
1161
1058
  List_iterator<Key> key_iterator(alter_info->key_list);
1162
1059
  List_iterator<Key> key_iterator2(alter_info->key_list);
1163
 
  uint key_parts=0, fk_key_count=0;
 
1060
  uint32_t key_parts=0, fk_key_count=0;
1164
1061
  bool primary_key=0,unique_key=0;
1165
1062
  Key *key, *key2;
1166
 
  uint tmp, key_number;
 
1063
  uint32_t tmp, key_number;
1167
1064
  /* special marker for keys to be ignored */
1168
1065
  static char ignore_key[1];
1169
1066
 
1175
1072
    if (key->type == Key::FOREIGN_KEY)
1176
1073
    {
1177
1074
      fk_key_count++;
 
1075
      if (((Foreign_key *)key)->validate(alter_info->create_list))
 
1076
        return true;
1178
1077
      Foreign_key *fk_key= (Foreign_key*) key;
1179
1078
      if (fk_key->ref_columns.elements &&
1180
1079
          fk_key->ref_columns.elements != fk_key->columns.elements)
1188
1087
      continue;
1189
1088
    }
1190
1089
    (*key_count)++;
1191
 
    tmp=file->max_key_parts();
 
1090
    tmp=cursor->getEngine()->max_key_parts();
1192
1091
    if (key->columns.elements > tmp)
1193
1092
    {
1194
1093
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
1231
1130
    else
1232
1131
      (*key_count)--;
1233
1132
    if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
1234
 
        !my_strcasecmp(system_charset_info,key->name.str, primary_key_name))
 
1133
        is_primary_key_name(key->name.str))
1235
1134
    {
1236
1135
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
1237
1136
      return(true);
1238
1137
    }
1239
1138
  }
1240
 
  tmp=file->max_keys();
 
1139
  tmp=cursor->getEngine()->max_keys();
1241
1140
  if (*key_count > tmp)
1242
1141
  {
1243
1142
    my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
1244
1143
    return(true);
1245
1144
  }
1246
1145
 
1247
 
  (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
1248
 
  key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
 
1146
  (*key_info_buffer)= key_info= (KEY*) memory::sql_calloc(sizeof(KEY) * (*key_count));
 
1147
  key_part_info=(KEY_PART_INFO*) memory::sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
1249
1148
  if (!*key_info_buffer || ! key_part_info)
1250
1149
    return(true);                               // Out of memory
1251
1150
 
1253
1152
  key_number=0;
1254
1153
  for (; (key=key_iterator++) ; key_number++)
1255
1154
  {
1256
 
    uint key_length=0;
 
1155
    uint32_t key_length=0;
1257
1156
    Key_part_spec *column;
1258
1157
 
1259
1158
    if (key->name.str == ignore_key)
1292
1191
    */
1293
1192
    key_info->block_size= (key->key_create_info.block_size ?
1294
1193
                           key->key_create_info.block_size :
1295
 
                           create_info->key_block_size);
 
1194
                           create_proto->options().key_block_size());
1296
1195
 
1297
1196
    if (key_info->block_size)
1298
1197
      key_info->flags|= HA_USES_BLOCK_SIZE;
1299
1198
 
1300
 
    uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
 
1199
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
1301
1200
                                           key->key_create_info.comment.str,
1302
1201
                                           key->key_create_info.comment.str +
1303
1202
                                           key->key_create_info.comment.length,
1307
1206
    {
1308
1207
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
1309
1208
               key->key_create_info.comment.str,"INDEX COMMENT",
1310
 
               (uint) INDEX_COMMENT_MAXLEN);
1311
 
      return(-1);
 
1209
               (uint32_t) INDEX_COMMENT_MAXLEN);
 
1210
      return -1;
1312
1211
    }
1313
1212
 
1314
1213
    key_info->comment.length= key->key_create_info.comment.length;
1318
1217
      key_info->comment.str= key->key_create_info.comment.str;
1319
1218
    }
1320
1219
 
 
1220
    message::Table::Field *protofield= NULL;
 
1221
 
1321
1222
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
1322
 
    for (uint column_nr=0 ; (column=cols++) ; column_nr++)
 
1223
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
1323
1224
    {
1324
 
      uint length;
 
1225
      uint32_t length;
1325
1226
      Key_part_spec *dup_column;
 
1227
      int proto_field_nr= 0;
1326
1228
 
1327
1229
      it.rewind();
1328
1230
      field=0;
1329
 
      while ((sql_field=it++) &&
 
1231
      while ((sql_field=it++) && ++proto_field_nr &&
1330
1232
             my_strcasecmp(system_charset_info,
1331
1233
                           column->field_name.str,
1332
1234
                           sql_field->field_name))
1339
1241
      while ((dup_column= cols2++) != column)
1340
1242
      {
1341
1243
        if (!my_strcasecmp(system_charset_info,
1342
 
                           column->field_name.str, dup_column->field_name.str))
 
1244
                           column->field_name.str, dup_column->field_name.str))
1343
1245
        {
1344
1246
          my_printf_error(ER_DUP_FIELDNAME,
1345
1247
                          ER(ER_DUP_FIELDNAME),MYF(0),
1348
1250
        }
1349
1251
      }
1350
1252
      cols2.rewind();
 
1253
 
 
1254
      if (create_proto->field_size() > 0)
 
1255
        protofield= create_proto->mutable_field(proto_field_nr - 1);
 
1256
 
1351
1257
      {
1352
 
        column->length*= sql_field->charset->mbmaxlen;
 
1258
        column->length*= sql_field->charset->mbmaxlen;
1353
1259
 
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;
 
1260
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
 
1261
        {
 
1262
          if (! (cursor->getEngine()->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
 
1263
          {
 
1264
            my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
 
1265
            return true;
 
1266
          }
 
1267
          if (! column->length)
 
1268
          {
 
1269
            my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
 
1270
            return true;
 
1271
          }
 
1272
        }
 
1273
        if (! (sql_field->flags & NOT_NULL_FLAG))
 
1274
        {
 
1275
          if (key->type == Key::PRIMARY)
 
1276
          {
 
1277
            /* Implicitly set primary key fields to NOT NULL for ISO conf. */
 
1278
            sql_field->flags|= NOT_NULL_FLAG;
1374
1279
            null_fields--;
1375
 
          }
1376
 
          else
 
1280
 
 
1281
            if (protofield)
 
1282
            {
 
1283
              message::Table::Field::FieldConstraints *constraints;
 
1284
              constraints= protofield->mutable_constraints();
 
1285
              constraints->set_is_nullable(false);
 
1286
            }
 
1287
 
 
1288
          }
 
1289
          else
1377
1290
          {
1378
1291
            key_info->flags|= HA_NULL_PART_KEY;
1379
 
            if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
 
1292
            if (! (cursor->getEngine()->check_flag(HTON_BIT_NULL_IN_KEY)))
1380
1293
            {
1381
1294
              my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
1382
 
              return(true);
 
1295
              return true;
1383
1296
            }
1384
1297
          }
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
 
        }
 
1298
        }
 
1299
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
 
1300
        {
 
1301
          if (column_nr == 0 || (cursor->getEngine()->check_flag(HTON_BIT_AUTO_PART_KEY)))
 
1302
            auto_increment--;                   // Field is used
 
1303
        }
1391
1304
      }
1392
1305
 
1393
1306
      key_part_info->fieldnr= field;
1397
1310
 
1398
1311
      if (column->length)
1399
1312
      {
1400
 
        if (f_is_blob(sql_field->pack_flag))
 
1313
        if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1401
1314
        {
1402
1315
          if ((length=column->length) > max_key_length ||
1403
 
              length > file->max_key_part_length())
 
1316
              length > cursor->getEngine()->max_key_part_length())
1404
1317
          {
1405
 
            length=min(max_key_length, file->max_key_part_length());
 
1318
            length= min(max_key_length, cursor->getEngine()->max_key_part_length());
1406
1319
            if (key->type == Key::MULTIPLE)
1407
1320
            {
1408
1321
              /* not a critical problem */
1409
1322
              char warn_buff[DRIZZLE_ERRMSG_SIZE];
1410
1323
              snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1411
1324
                       length);
1412
 
              push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1325
              push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1413
1326
                           ER_TOO_LONG_KEY, warn_buff);
1414
1327
              /* Align key length to multibyte char boundary */
1415
1328
              length-= length % sql_field->charset->mbmaxlen;
1422
1335
          }
1423
1336
        }
1424
1337
        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)))
 
1338
            ! Field::type_can_have_key_part(sql_field->sql_type)))
1430
1339
        {
1431
1340
          my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
1432
1341
          return(true);
1433
1342
        }
1434
 
        else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
 
1343
        else if (! (cursor->getEngine()->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
 
1344
        {
1435
1345
          length=column->length;
 
1346
        }
1436
1347
      }
1437
1348
      else if (length == 0)
1438
1349
      {
1439
1350
        my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
1440
1351
          return(true);
1441
1352
      }
1442
 
      if (length > file->max_key_part_length())
 
1353
      if (length > cursor->getEngine()->max_key_part_length())
1443
1354
      {
1444
 
        length= file->max_key_part_length();
 
1355
        length= cursor->getEngine()->max_key_part_length();
1445
1356
        if (key->type == Key::MULTIPLE)
1446
1357
        {
1447
1358
          /* not a critical problem */
1448
1359
          char warn_buff[DRIZZLE_ERRMSG_SIZE];
1449
1360
          snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
1450
1361
                   length);
1451
 
          push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1362
          push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1452
1363
                       ER_TOO_LONG_KEY, warn_buff);
1453
1364
          /* Align key length to multibyte char boundary */
1454
1365
          length-= length % sql_field->charset->mbmaxlen;
1464
1375
      if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
1465
1376
          (length >= KEY_DEFAULT_PACK_LENGTH &&
1466
1377
           (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
1467
 
            sql_field->pack_flag & FIELDFLAG_BLOB)))
 
1378
      sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
1468
1379
      {
1469
 
        if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
 
1380
        if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
1470
1381
            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;
 
1382
          key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 
1383
        else
 
1384
          key_info->flags|= HA_PACK_KEY;
1474
1385
      }
1475
1386
      /* Check if the key segment is partial, set the key flag accordingly */
1476
1387
      if (length != sql_field->key_length)
1490
1401
                       MYF(0));
1491
1402
            return(true);
1492
1403
          }
1493
 
          key_name=primary_key_name;
 
1404
          static const char pkey_name[]= "PRIMARY";
 
1405
          key_name=pkey_name;
1494
1406
          primary_key=1;
1495
1407
        }
1496
1408
        else if (!(key_name= key->name.str))
1520
1432
    key_info++;
1521
1433
  }
1522
1434
  if (!unique_key && !primary_key &&
1523
 
      (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
 
1435
      (cursor->getEngine()->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1524
1436
  {
1525
1437
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1526
1438
    return(true);
1531
1443
    return(true);
1532
1444
  }
1533
1445
  /* Sort keys in optimized order */
1534
 
  my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
 
1446
  my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1535
1447
           (qsort_cmp) sort_keys);
1536
 
  create_info->null_bits= null_fields;
1537
1448
 
1538
1449
  /* Check fields. */
1539
1450
  it.rewind();
1541
1452
  {
1542
1453
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1543
1454
 
1544
 
    if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
 
1455
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1545
1456
        !sql_field->def &&
1546
1457
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1547
1458
        (sql_field->flags & NOT_NULL_FLAG) &&
1569
1480
  return(false);
1570
1481
}
1571
1482
 
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
1483
/*
1606
1484
  Extend long VARCHAR fields to blob & prepare field if it's a blob
1607
1485
 
1615
1493
        In this case the error is given
1616
1494
*/
1617
1495
 
1618
 
static bool prepare_blob_field(THD *thd __attribute__((unused)),
1619
 
                               Create_field *sql_field)
 
1496
static bool prepare_blob_field(Session *,
 
1497
                               CreateField *sql_field)
1620
1498
{
1621
1499
 
1622
1500
  if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
1624
1502
  {
1625
1503
    my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1626
1504
             MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1627
 
    return(1);
 
1505
    return 1;
1628
1506
  }
1629
 
    
 
1507
 
1630
1508
  if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1631
1509
  {
1632
1510
    if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1633
1511
    {
1634
1512
      /* The user has given a length to the blob column */
1635
 
      sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1636
1513
      sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1637
1514
    }
1638
1515
    sql_field->length= 0;
1639
1516
  }
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
 
/*
 
1517
  return 0;
 
1518
}
 
1519
 
 
1520
 
 
1521
/*
 
1522
  Ignore the name of this function... it locks :(
 
1523
 
1682
1524
  Create a table
1683
1525
 
1684
1526
  SYNOPSIS
1685
1527
    mysql_create_table_no_lock()
1686
 
    thd                 Thread object
 
1528
    session                     Thread object
1687
1529
    db                  Database
1688
1530
    table_name          Table name
1689
1531
    create_info         Create information (like MAX_ROWS)
1690
1532
    fields              List of fields to create
1691
1533
    keys                List of keys to create
1692
1534
    internal_tmp_table  Set to 1 if this is an internal temporary table
1693
 
                        (From ALTER TABLE)
1694
 
    select_field_count  
 
1535
                        (From ALTER Table)
 
1536
    select_field_count
1695
1537
 
1696
1538
  DESCRIPTION
1697
1539
    If one creates a temporary table, this is automatically opened
1701
1543
    that concurrent operations won't intervene. mysql_create_table()
1702
1544
    is a wrapper that can be used for this.
1703
1545
 
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
1546
  RETURN VALUES
1710
1547
    false OK
1711
1548
    true  error
1712
1549
*/
1713
1550
 
1714
 
bool mysql_create_table_no_lock(THD *thd,
1715
 
                                const char *db, const char *table_name,
 
1551
bool mysql_create_table_no_lock(Session *session,
 
1552
                                TableIdentifier &identifier,
1716
1553
                                HA_CREATE_INFO *create_info,
1717
 
                                Alter_info *alter_info,
 
1554
                                message::Table *table_proto,
 
1555
                                AlterInfo *alter_info,
1718
1556
                                bool internal_tmp_table,
1719
 
                                uint select_field_count)
 
1557
                                uint32_t select_field_count,
 
1558
                                bool is_if_not_exists)
1720
1559
{
1721
 
  char          path[FN_REFLEN];
1722
 
  uint          path_length;
1723
 
  const char    *alias;
1724
1560
  uint          db_options, key_count;
1725
1561
  KEY           *key_info_buffer;
1726
 
  handler       *file;
 
1562
  Cursor        *cursor;
1727
1563
  bool          error= true;
 
1564
  TableShare share;
 
1565
  bool lex_identified_temp_table=
 
1566
    (table_proto->type() == drizzled::message::Table::TEMPORARY);
 
1567
 
1728
1568
  /* Check for duplicate fields and check type of table to create */
1729
1569
  if (!alter_info->create_list.elements)
1730
1570
  {
1731
1571
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1732
1572
               MYF(0));
1733
 
    return(true);
 
1573
    return true;
1734
1574
  }
1735
 
  if (check_engine(thd, table_name, create_info))
1736
 
    return(true);
 
1575
  assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
1737
1576
  db_options= create_info->table_options;
1738
1577
  if (create_info->row_type == ROW_TYPE_DYNAMIC)
1739
1578
    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)))
 
1579
  if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1743
1580
  {
1744
 
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1745
 
    return(true);
 
1581
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
 
1582
    return true;
1746
1583
  }
1747
1584
 
1748
 
  set_table_default_charset(thd, create_info, (char*) db);
 
1585
  set_table_default_charset(create_info, identifier.getDBName());
1749
1586
 
1750
 
  if (mysql_prepare_create_table(thd, create_info, alter_info,
 
1587
  /* Check if table exists */
 
1588
  if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1751
1589
                                 internal_tmp_table,
1752
 
                                 &db_options, file,
1753
 
                          &key_info_buffer, &key_count,
1754
 
                          select_field_count))
 
1590
                                 &db_options, cursor,
 
1591
                                 &key_info_buffer, &key_count,
 
1592
                                 select_field_count))
1755
1593
    goto err;
1756
1594
 
1757
 
      /* Check if table exists */
1758
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1759
 
  {
1760
 
    path_length= build_tmptable_filename(thd, path, sizeof(path));
1761
 
    create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1762
 
  }
1763
 
  else  
1764
 
  {
1765
 
 #ifdef FN_DEVCHAR
1766
 
    /* check if the table name contains FN_DEVCHAR when defined */
1767
 
    if (strchr(alias, FN_DEVCHAR))
1768
 
    {
1769
 
      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1770
 
      return(true);
1771
 
    }
1772
 
#endif
1773
 
    path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1774
 
                                      internal_tmp_table ? FN_IS_TMP : 0);
1775
 
  }
1776
 
 
1777
1595
  /* Check if table already exists */
1778
 
  if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1779
 
      find_temporary_table(thd, db, table_name))
 
1596
  if (lex_identified_temp_table &&
 
1597
      session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1780
1598
  {
1781
 
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1599
    if (is_if_not_exists)
1782
1600
    {
1783
1601
      create_info->table_existed= 1;            // Mark that table existed
1784
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1602
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1785
1603
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1786
 
                          alias);
 
1604
                          identifier.getTableName());
1787
1605
      error= 0;
1788
1606
      goto err;
1789
1607
    }
1790
 
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
 
1608
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1791
1609
    goto err;
1792
1610
  }
1793
1611
 
1794
 
  VOID(pthread_mutex_lock(&LOCK_open));
1795
 
  if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1612
  pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
 
1613
  if (!internal_tmp_table && ! lex_identified_temp_table)
1796
1614
  {
1797
 
    if (!access(path,F_OK))
 
1615
    if (plugin::StorageEngine::getTableDefinition(*session,
 
1616
                                                  identifier)==EEXIST)
1798
1617
    {
1799
 
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1800
 
        goto warn;
1801
 
      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1618
      if (is_if_not_exists)
 
1619
      {
 
1620
        error= false;
 
1621
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1622
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1623
                            identifier.getTableName());
 
1624
        create_info->table_existed= 1;          // Mark that table existed
 
1625
      }
 
1626
      else 
 
1627
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1628
 
1802
1629
      goto unlock_and_end;
1803
1630
    }
1804
1631
    /*
1805
1632
      We don't assert here, but check the result, because the table could be
1806
1633
      in the table definition cache and in the same time the .frm could be
1807
1634
      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.
 
1635
      the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1809
1636
      Then she could create the table. This case is pretty obscure and
1810
1637
      therefore we don't introduce a new error message only for it.
1811
1638
    */
1812
 
    if (get_cached_table_share(db, alias))
 
1639
    if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
1813
1640
    {
1814
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
1641
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1815
1642
      goto unlock_and_end;
1816
1643
    }
1817
1644
  }
1823
1650
    unless user specified CREATE TABLE IF EXISTS
1824
1651
    The LOCK_open mutex has been locked to make sure no
1825
1652
    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!
 
1653
    it's not on disk as a frm cursor, no one could be using it!
1827
1654
  */
1828
 
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
1655
  if (! lex_identified_temp_table)
1829
1656
  {
1830
 
    bool create_if_not_exists =
1831
 
      create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1832
 
    int retcode = ha_table_exists_in_engine(thd, db, table_name);
 
1657
    int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
 
1658
 
1833
1659
    switch (retcode)
1834
1660
    {
1835
 
      case HA_ERR_NO_SUCH_TABLE:
 
1661
      case ENOENT:
1836
1662
        /* Normal case, no table exists. we can go and create it */
1837
1663
        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;
 
1664
      case EEXIST:
 
1665
        if (is_if_not_exists)
 
1666
        {
 
1667
          error= false;
 
1668
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1669
                              ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
 
1670
                              identifier.getTableName());
 
1671
          create_info->table_existed= 1;                // Mark that table existed
 
1672
          goto unlock_and_end;
 
1673
        }
 
1674
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
 
1675
        goto unlock_and_end;
1845
1676
      default:
1846
 
        my_error(retcode, MYF(0),table_name);
 
1677
        my_error(retcode, MYF(0), identifier.getTableName());
1847
1678
        goto unlock_and_end;
1848
1679
    }
1849
1680
  }
1850
1681
 
1851
 
  thd_proc_info(thd, "creating table");
 
1682
  session->set_proc_info("creating table");
1852
1683
  create_info->table_existed= 0;                // Mark that table is created
1853
1684
 
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
 
  create_info->table_options=db_options;
1878
 
 
1879
 
  path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1880
 
  if (rea_create_table(thd, path, db, table_name,
 
1685
  create_info->table_options= db_options;
 
1686
 
 
1687
  if (rea_create_table(session, identifier,
 
1688
                       table_proto,
1881
1689
                       create_info, alter_info->create_list,
1882
 
                       key_count, key_info_buffer, file))
 
1690
                       key_count, key_info_buffer))
1883
1691
    goto unlock_and_end;
1884
1692
 
1885
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
1693
  if (lex_identified_temp_table)
1886
1694
  {
1887
1695
    /* Open table and put in temporary table list */
1888
 
    if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
 
1696
    if (!(session->open_temporary_table(identifier)))
1889
1697
    {
1890
 
      (void) rm_temporary_table(create_info->db_type, path, false);
 
1698
      (void) session->rm_temporary_table(create_info->db_type, identifier);
1891
1699
      goto unlock_and_end;
1892
1700
    }
1893
 
    thd->thread_specific_used= true;
1894
1701
  }
1895
1702
 
1896
1703
  /*
1900
1707
    - The binary log is not open.
1901
1708
    Otherwise, the statement shall be binlogged.
1902
1709
   */
1903
 
  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);
 
1710
  if (!internal_tmp_table && ! lex_identified_temp_table)
 
1711
    write_bin_log(session, session->query, session->query_length);
1908
1712
  error= false;
1909
1713
unlock_and_end:
1910
 
  VOID(pthread_mutex_unlock(&LOCK_open));
 
1714
  pthread_mutex_unlock(&LOCK_open);
1911
1715
 
1912
1716
err:
1913
 
  thd_proc_info(thd, "After create");
1914
 
  delete file;
 
1717
  session->set_proc_info("After create");
 
1718
  delete cursor;
1915
1719
  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
1720
}
1925
1721
 
1926
1722
 
1928
1724
  Database locking aware wrapper for mysql_create_table_no_lock(),
1929
1725
*/
1930
1726
 
1931
 
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
 
1727
bool mysql_create_table(Session *session,
 
1728
                        TableIdentifier &identifier,
1932
1729
                        HA_CREATE_INFO *create_info,
1933
 
                        Alter_info *alter_info,
 
1730
                        message::Table *table_proto,
 
1731
                        AlterInfo *alter_info,
1934
1732
                        bool internal_tmp_table,
1935
 
                        uint select_field_count)
 
1733
                        uint32_t select_field_count,
 
1734
                        bool is_if_not_exists)
1936
1735
{
1937
 
  TABLE *name_lock= 0;
 
1736
  Table *name_lock= NULL;
1938
1737
  bool result;
1939
 
 
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
 
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1958
 
  {
1959
 
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
1738
  bool lex_identified_temp_table=
 
1739
    (table_proto->type() == drizzled::message::Table::TEMPORARY);
 
1740
 
 
1741
  if (! lex_identified_temp_table)
 
1742
  {
 
1743
    if (session->lock_table_name_if_not_cached(identifier.getDBName(),
 
1744
                                               identifier.getTableName(),
 
1745
                                               &name_lock))
1960
1746
    {
1961
1747
      result= true;
1962
1748
      goto unlock;
1963
1749
    }
1964
 
    if (!name_lock)
 
1750
    if (name_lock == NULL)
1965
1751
    {
1966
 
      if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
1752
      if (is_if_not_exists)
1967
1753
      {
1968
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1754
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1969
1755
                            ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1970
 
                            table_name);
 
1756
                            identifier.getTableName());
1971
1757
        create_info->table_existed= 1;
1972
1758
        result= false;
1973
1759
      }
1974
1760
      else
1975
1761
      {
1976
 
        my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
 
1762
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1977
1763
        result= true;
1978
1764
      }
1979
1765
      goto unlock;
1980
1766
    }
1981
1767
  }
1982
1768
 
1983
 
  result= mysql_create_table_no_lock(thd, db, table_name, create_info,
 
1769
  result= mysql_create_table_no_lock(session,
 
1770
                                     identifier,
 
1771
                                     create_info,
 
1772
                                     table_proto,
1984
1773
                                     alter_info,
1985
1774
                                     internal_tmp_table,
1986
 
                                     select_field_count);
 
1775
                                     select_field_count,
 
1776
                                     is_if_not_exists);
1987
1777
 
1988
1778
unlock:
1989
1779
  if (name_lock)
1990
1780
  {
1991
 
    pthread_mutex_lock(&LOCK_open);
1992
 
    unlink_open_table(thd, name_lock, false);
 
1781
    pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
 
1782
    session->unlink_open_table(name_lock);
1993
1783
    pthread_mutex_unlock(&LOCK_open);
1994
1784
  }
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);
 
1785
 
1999
1786
  return(result);
2000
1787
}
2001
1788
 
2020
1807
  char buff[MAX_FIELD_NAME],*buff_end;
2021
1808
 
2022
1809
  if (!check_if_keyname_exists(field_name,start,end) &&
2023
 
      my_strcasecmp(system_charset_info,field_name,primary_key_name))
 
1810
      !is_primary_key_name(field_name))
2024
1811
    return (char*) field_name;                  // Use fieldname
2025
 
  buff_end=strmake(buff,field_name, sizeof(buff)-4);
 
1812
 
 
1813
  buff_end= strncpy(buff, field_name, sizeof(buff)-4);
 
1814
  buff_end+= strlen(buff);
2026
1815
 
2027
1816
  /*
2028
1817
    Only 3 chars + '\0' left, so need to limit to 2 digit
2029
1818
    This is ok as we can't have more than 100 keys anyway
2030
1819
  */
2031
 
  for (uint i=2 ; i< 100; i++)
 
1820
  for (uint32_t i=2 ; i< 100; i++)
2032
1821
  {
2033
1822
    *buff_end= '_';
2034
1823
    int10_to_str(i, buff_end+1, 10);
2035
1824
    if (!check_if_keyname_exists(buff,start,end))
2036
 
      return sql_strdup(buff);
 
1825
      return memory::sql_strdup(buff);
2037
1826
  }
2038
1827
  return (char*) "not_specified";               // Should never happen
2039
1828
}
2043
1832
** Alter a table definition
2044
1833
****************************************************************************/
2045
1834
 
2046
 
 
2047
1835
/*
2048
1836
  Rename a table.
2049
1837
 
2050
1838
  SYNOPSIS
2051
1839
    mysql_rename_table()
2052
 
      base                      The handlerton handle.
 
1840
      base                      The plugin::StorageEngine handle.
2053
1841
      old_db                    The old database name.
2054
1842
      old_name                  The old table name.
2055
1843
      new_db                    The new database name.
2057
1845
      flags                     flags for build_table_filename().
2058
1846
                                FN_FROM_IS_TMP old_name is temporary.
2059
1847
                                FN_TO_IS_TMP   new_name is temporary.
2060
 
                                NO_FRM_RENAME  Don't rename the FRM file
2061
 
                                but only the table in the storage engine.
2062
1848
 
2063
1849
  RETURN
2064
1850
    false   OK
2066
1852
*/
2067
1853
 
2068
1854
bool
2069
 
mysql_rename_table(handlerton *base, const char *old_db,
 
1855
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
2070
1856
                   const char *old_name, const char *new_db,
2071
 
                   const char *new_name, uint flags)
 
1857
                   const char *new_name, uint32_t flags)
2072
1858
{
2073
 
  THD *thd= current_thd;
2074
 
  char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
 
1859
  Session *session= current_session;
 
1860
  char from[FN_REFLEN], to[FN_REFLEN];
2075
1861
  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, "",
 
1862
  int error= 0;
 
1863
 
 
1864
  assert(base);
 
1865
 
 
1866
  build_table_filename(from, sizeof(from), old_db, old_name,
2084
1867
                       flags & FN_FROM_IS_TMP);
2085
 
  build_table_filename(to, sizeof(to), new_db, new_name, "",
 
1868
  build_table_filename(to, sizeof(to), new_db, new_name,
2086
1869
                       flags & FN_TO_IS_TMP);
2087
1870
 
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))
 
1871
  if (!(error= base->renameTable(session, from_base, to_base)))
 
1872
  {
 
1873
    if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
 
1874
       && rename_table_proto_file(from_base, to_base))
2111
1875
    {
2112
 
      error=my_errno;
2113
 
      /* Restore old file name */
2114
 
      if (file)
2115
 
        file->ha_rename_table(to_base, from_base);
 
1876
      error= errno;
 
1877
      base->renameTable(session, to_base, from_base);
2116
1878
    }
2117
1879
  }
2118
 
  delete file;
 
1880
 
2119
1881
  if (error == HA_ERR_WRONG_COMMAND)
2120
 
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
 
1882
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
2121
1883
  else if (error)
2122
1884
    my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
2123
1885
  return(error != 0);
2129
1891
 
2130
1892
  SYNOPSIS
2131
1893
    wait_while_table_is_used()
2132
 
    thd                 Thread handler
 
1894
    session                     Thread Cursor
2133
1895
    table               Table to remove from cache
2134
1896
    function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
2135
1897
                        HA_EXTRA_FORCE_REOPEN if table is not be used
2143
1905
    Win32 clients must also have a WRITE LOCK on the table !
2144
1906
*/
2145
1907
 
2146
 
void wait_while_table_is_used(THD *thd, TABLE *table,
 
1908
void wait_while_table_is_used(Session *session, Table *table,
2147
1909
                              enum ha_extra_function function)
2148
1910
{
2149
1911
 
2150
1912
  safe_mutex_assert_owner(&LOCK_open);
2151
1913
 
2152
 
  VOID(table->file->extra(function));
 
1914
  table->cursor->extra(function);
2153
1915
  /* Mark all tables that are in use as 'old' */
2154
 
  mysql_lock_abort(thd, table, true);   /* end threads waiting on lock */
 
1916
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
2155
1917
 
2156
1918
  /* Wait until all there are no other threads that has this table open */
2157
 
  remove_table_from_cache(thd, table->s->db.str,
 
1919
  remove_table_from_cache(session, table->s->db.str,
2158
1920
                          table->s->table_name.str,
2159
1921
                          RTFC_WAIT_OTHER_THREAD_FLAG);
2160
 
  return;
2161
1922
}
2162
1923
 
2163
1924
/*
2165
1926
 
2166
1927
  SYNOPSIS
2167
1928
    close_cached_table()
2168
 
    thd                 Thread handler
 
1929
    session                     Thread Cursor
2169
1930
    table               Table to remove from cache
2170
1931
 
2171
1932
  NOTES
2177
1938
    Win32 clients must also have a WRITE LOCK on the table !
2178
1939
*/
2179
1940
 
2180
 
void close_cached_table(THD *thd, TABLE *table)
 
1941
void Session::close_cached_table(Table *table)
2181
1942
{
2182
1943
 
2183
 
  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
 
1944
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
2184
1945
  /* Close lock if this is not got with LOCK TABLES */
2185
 
  if (thd->lock)
 
1946
  if (lock)
2186
1947
  {
2187
 
    mysql_unlock_tables(thd, thd->lock);
2188
 
    thd->lock=0;                        // Start locked threads
 
1948
    mysql_unlock_tables(this, lock);
 
1949
    lock= NULL;                 // Start locked threads
2189
1950
  }
2190
1951
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
2191
 
  unlink_open_table(thd, table, true);
 
1952
  unlink_open_table(table);
2192
1953
 
2193
1954
  /* When lock on LOCK_open is freed other threads can continue */
2194
1955
  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
 
 
 
1956
}
2356
1957
 
2357
1958
/*
2358
1959
  RETURN VALUES
2359
1960
    false Message sent to net (admin operation went ok)
2360
 
    true  Message should be sent by caller 
 
1961
    true  Message should be sent by caller
2361
1962
          (admin operation or network communication failed)
2362
1963
*/
2363
 
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
 
1964
static bool mysql_admin_table(Session* session, TableList* tables,
2364
1965
                              HA_CHECK_OPT* check_opt,
2365
1966
                              const char *operator_name,
2366
1967
                              thr_lock_type lock_type,
2367
1968
                              bool open_for_modify,
2368
 
                              bool no_warnings_for_error,
2369
 
                              uint extra_open_options,
2370
 
                              int (*prepare_func)(THD *, TABLE_LIST *,
2371
 
                                                  HA_CHECK_OPT *),
2372
 
                              int (handler::*operator_func)(THD *,
 
1969
                              int (Cursor::*operator_func)(Session *,
2373
1970
                                                            HA_CHECK_OPT *))
2374
1971
{
2375
 
  TABLE_LIST *table;
2376
 
  SELECT_LEX *select= &thd->lex->select_lex;
 
1972
  TableList *table;
 
1973
  Select_Lex *select= &session->lex->select_lex;
2377
1974
  List<Item> field_list;
2378
1975
  Item *item;
2379
 
  Protocol *protocol= thd->protocol;
2380
 
  LEX *lex= thd->lex;
 
1976
  LEX *lex= session->lex;
2381
1977
  int result_code= 0;
2382
1978
  const CHARSET_INFO * const cs= system_charset_info;
2383
1979
 
2384
 
  if (end_active_trans(thd))
2385
 
    return(1);
 
1980
  if (! session->endActiveTransaction())
 
1981
    return 1;
2386
1982
  field_list.push_back(item = new Item_empty_string("Table",
2387
1983
                                                    NAME_CHAR_LEN * 2,
2388
1984
                                                    cs));
2393
1989
  item->maybe_null = 1;
2394
1990
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
2395
1991
  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);
 
1992
  if (session->client->sendFields(&field_list))
 
1993
    return true;
2401
1994
 
2402
1995
  for (table= tables; table; table= table->next_local)
2403
1996
  {
2405
1998
    char* db = table->db;
2406
1999
    bool fatal_error=0;
2407
2000
 
2408
 
    strxmov(table_name, db, ".", table->table_name, NullS);
2409
 
    thd->open_options|= extra_open_options;
 
2001
    sprintf(table_name,"%s.%s",db,table->table_name);
2410
2002
    table->lock_type= lock_type;
2411
2003
    /* open only one table from local list of command */
2412
2004
    {
2413
 
      TABLE_LIST *save_next_global, *save_next_local;
 
2005
      TableList *save_next_global, *save_next_local;
2414
2006
      save_next_global= table->next_global;
2415
2007
      table->next_global= 0;
2416
2008
      save_next_local= table->next_local;
2417
2009
      table->next_local= 0;
2418
 
      select->table_list.first= (uchar*)table;
 
2010
      select->table_list.first= (unsigned char*)table;
2419
2011
      /*
2420
2012
        Time zone tables and SP tables can be add to lex->query_tables list,
2421
2013
        so it have to be prepared.
2425
2017
      lex->query_tables= table;
2426
2018
      lex->query_tables_last= &table->next_global;
2427
2019
      lex->query_tables_own_last= 0;
2428
 
      thd->no_warnings_for_error= no_warnings_for_error;
2429
 
      table->required_type=FRMTYPE_TABLE;
 
2020
      session->no_warnings_for_error= 0;
2430
2021
 
2431
 
      open_and_lock_tables(thd, table);
2432
 
      thd->no_warnings_for_error= 0;
 
2022
      session->openTablesLock(table);
 
2023
      session->no_warnings_for_error= 0;
2433
2024
      table->next_global= save_next_global;
2434
2025
      table->next_local= save_next_local;
2435
 
      thd->open_options&= ~extra_open_options;
2436
 
    }
2437
 
 
2438
 
    if (prepare_func)
2439
 
    {
2440
 
      switch ((*prepare_func)(thd, table, check_opt)) {
2441
 
      case  1:           // error, message written to net
2442
 
        ha_autocommit_or_rollback(thd, 1);
2443
 
        end_trans(thd, ROLLBACK);
2444
 
        close_thread_tables(thd);
2445
 
        continue;
2446
 
      case -1:           // error, message could be written to net
2447
 
        /* purecov: begin inspected */
2448
 
        goto err;
2449
 
        /* purecov: end */
2450
 
      default:           // should be 0 otherwise
2451
 
        ;
2452
 
      }
2453
2026
    }
2454
2027
 
2455
2028
    /*
2456
 
      CHECK TABLE command is only command where VIEW allowed here and this
 
2029
      CHECK Table command is only command where VIEW allowed here and this
2457
2030
      command use only temporary teble method for VIEWs resolving => there
2458
2031
      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
 
2032
      succeed then table->table will have real Table pointer as value (in
2460
2033
      case of join view substitution table->table can be 0, but here it is
2461
2034
      impossible)
2462
2035
    */
2463
2036
    if (!table->table)
2464
2037
    {
2465
 
      if (!thd->warn_list.elements)
2466
 
        push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2038
      if (!session->warn_list.elements)
 
2039
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
2467
2040
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
 
2041
      result_code= HA_ADMIN_CORRUPT;
2468
2042
      goto send_result;
2469
2043
    }
2470
2044
 
2471
2045
    if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
2472
2046
    {
2473
 
      /* purecov: begin inspected */
2474
2047
      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);
 
2048
      uint32_t length;
 
2049
      session->client->store(table_name);
 
2050
      session->client->store(operator_name);
 
2051
      session->client->store(STRING_WITH_LEN("error"));
2480
2052
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
2481
2053
                       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);
 
2054
      session->client->store(buff, length);
 
2055
      ha_autocommit_or_rollback(session, 0);
 
2056
      session->endTransaction(COMMIT);
 
2057
      session->close_thread_tables();
2486
2058
      lex->reset_query_tables_list(false);
2487
2059
      table->table=0;                           // For query cache
2488
 
      if (protocol->write())
 
2060
      if (session->client->flush())
2489
2061
        goto err;
2490
2062
      continue;
2491
 
      /* purecov: end */
2492
2063
    }
2493
2064
 
2494
2065
    /* Close all instances of the table to allow repair to rename files */
2495
2066
    if (lock_type == TL_WRITE && table->table->s->version)
2496
2067
    {
2497
 
      pthread_mutex_lock(&LOCK_open);
2498
 
      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 
2068
      pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
 
2069
      const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
2499
2070
                                              "Waiting to get writelock");
2500
 
      mysql_lock_abort(thd,table->table, true);
2501
 
      remove_table_from_cache(thd, table->table->s->db.str,
 
2071
      mysql_lock_abort(session,table->table);
 
2072
      remove_table_from_cache(session, table->table->s->db.str,
2502
2073
                              table->table->s->table_name.str,
2503
2074
                              RTFC_WAIT_OTHER_THREAD_FLAG |
2504
2075
                              RTFC_CHECK_KILLED_FLAG);
2505
 
      thd->exit_cond(old_message);
2506
 
      if (thd->killed)
 
2076
      session->exit_cond(old_message);
 
2077
      if (session->killed)
2507
2078
        goto err;
2508
2079
      open_for_modify= 0;
2509
2080
    }
2510
2081
 
2511
 
    if (table->table->s->crashed && operator_func == &handler::ha_check)
2512
 
    {
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())
2521
 
        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);
 
2082
    result_code = (table->table->cursor->*operator_func)(session, check_opt);
2550
2083
 
2551
2084
send_result:
2552
2085
 
2553
2086
    lex->cleanup_after_one_table_open();
2554
 
    thd->clear_error();  // these errors shouldn't get client
 
2087
    session->clear_error();  // these errors shouldn't get client
2555
2088
    {
2556
 
      List_iterator_fast<DRIZZLE_ERROR> it(thd->warn_list);
 
2089
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
2557
2090
      DRIZZLE_ERROR *err;
2558
2091
      while ((err= it++))
2559
2092
      {
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())
 
2093
        session->client->store(table_name);
 
2094
        session->client->store(operator_name);
 
2095
        session->client->store(warning_level_names[err->level].str,
 
2096
                               warning_level_names[err->level].length);
 
2097
        session->client->store(err->msg);
 
2098
        if (session->client->flush())
2568
2099
          goto err;
2569
2100
      }
2570
 
      drizzle_reset_errors(thd, true);
 
2101
      drizzle_reset_errors(session, true);
2571
2102
    }
2572
 
    protocol->prepare_for_resend();
2573
 
    protocol->store(table_name, system_charset_info);
2574
 
    protocol->store(operator_name, system_charset_info);
2575
 
 
2576
 
send_result_message:
 
2103
    session->client->store(table_name);
 
2104
    session->client->store(operator_name);
2577
2105
 
2578
2106
    switch (result_code) {
2579
2107
    case HA_ADMIN_NOT_IMPLEMENTED:
2580
2108
      {
2581
2109
        char buf[ERRMSGSIZE+20];
2582
 
        uint length=snprintf(buf, ERRMSGSIZE,
 
2110
        uint32_t length=snprintf(buf, ERRMSGSIZE,
2583
2111
                             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);
 
2112
        session->client->store(STRING_WITH_LEN("note"));
 
2113
        session->client->store(buf, length);
2596
2114
      }
2597
2115
      break;
2598
2116
 
2599
2117
    case HA_ADMIN_OK:
2600
 
      protocol->store(STRING_WITH_LEN("status"), system_charset_info);
2601
 
      protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
 
2118
      session->client->store(STRING_WITH_LEN("status"));
 
2119
      session->client->store(STRING_WITH_LEN("OK"));
2602
2120
      break;
2603
2121
 
2604
2122
    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);
 
2123
      session->client->store(STRING_WITH_LEN("status"));
 
2124
      session->client->store(STRING_WITH_LEN("Operation failed"));
2608
2125
      break;
2609
2126
 
2610
2127
    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);
 
2128
      session->client->store(STRING_WITH_LEN("status"));
 
2129
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
2614
2130
      open_for_modify= false;
2615
2131
      break;
2616
2132
 
2617
2133
    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);
 
2134
      session->client->store(STRING_WITH_LEN("status"));
 
2135
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
2621
2136
      break;
2622
2137
 
2623
2138
    case HA_ADMIN_CORRUPT:
2624
 
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2625
 
      protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
 
2139
      session->client->store(STRING_WITH_LEN("error"));
 
2140
      session->client->store(STRING_WITH_LEN("Corrupt"));
2626
2141
      fatal_error=1;
2627
2142
      break;
2628
2143
 
2629
2144
    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);
2633
 
      break;
2634
 
 
2635
 
    case HA_ADMIN_TRY_ALTER:
2636
 
    {
2637
 
      /*
2638
 
        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,
2640
 
        reopen the table and do ha_innobase::analyze() on it.
2641
 
      */
2642
 
      ha_autocommit_or_rollback(thd, 0);
2643
 
      close_thread_tables(thd);
2644
 
      TABLE_LIST *save_next_local= table->next_local,
2645
 
                 *save_next_global= table->next_global;
2646
 
      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);
2650
 
      /*
2651
 
        mysql_recreate_table() can push OK or ERROR.
2652
 
        Clear 'OK' status. If there is an error, keep it:
2653
 
        we will store the error message in a result set row 
2654
 
        and then clear.
2655
 
      */
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);
2660
 
      if (!result_code) // recreation went ok
2661
 
      {
2662
 
        if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
2663
 
            ((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
2664
 
          result_code= 0; // analyze went ok
2665
 
      }
2666
 
      if (result_code) // either mysql_recreate_table or analyze failed
2667
 
      {
2668
 
        assert(thd->is_error());
2669
 
        if (thd->is_error())
2670
 
        {
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();
2688
 
        }
2689
 
      }
2690
 
      result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
2691
 
      table->next_local= save_next_local;
2692
 
      table->next_global= save_next_global;
2693
 
      goto send_result_message;
2694
 
    }
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
 
    case HA_ADMIN_NEEDS_UPGRADE:
2704
 
    case HA_ADMIN_NEEDS_ALTER:
2705
 
    {
2706
 
      char buf[ERRMSGSIZE];
2707
 
      uint length;
2708
 
 
2709
 
      protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2710
 
      length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
2711
 
      protocol->store(buf, length, system_charset_info);
2712
 
      fatal_error=1;
2713
 
      break;
2714
 
    }
 
2145
      session->client->store(STRING_WITH_LEN("error"));
 
2146
      session->client->store(STRING_WITH_LEN("Invalid argument"));
 
2147
      break;
2715
2148
 
2716
2149
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
2717
2150
      {
2718
2151
        char buf[ERRMSGSIZE+20];
2719
 
        uint length=snprintf(buf, ERRMSGSIZE,
2720
 
                             "Unknown - internal error %d during operation",
 
2152
        uint32_t length=snprintf(buf, ERRMSGSIZE,
 
2153
                             _("Unknown - internal error %d during operation"),
2721
2154
                             result_code);
2722
 
        protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2723
 
        protocol->store(buf, length, system_charset_info);
 
2155
        session->client->store(STRING_WITH_LEN("error"));
 
2156
        session->client->store(buf, length);
2724
2157
        fatal_error=1;
2725
2158
        break;
2726
2159
      }
2732
2165
      else if (open_for_modify)
2733
2166
      {
2734
2167
        if (table->table->s->tmp_table)
2735
 
          table->table->file->info(HA_STATUS_CONST);
 
2168
          table->table->cursor->info(HA_STATUS_CONST);
2736
2169
        else
2737
2170
        {
2738
2171
          pthread_mutex_lock(&LOCK_open);
2739
 
          remove_table_from_cache(thd, table->table->s->db.str,
 
2172
          remove_table_from_cache(session, table->table->s->db.str,
2740
2173
                                  table->table->s->table_name.str, RTFC_NO_FLAG);
2741
2174
          pthread_mutex_unlock(&LOCK_open);
2742
2175
        }
2743
2176
      }
2744
2177
    }
2745
 
    ha_autocommit_or_rollback(thd, 0);
2746
 
    end_trans(thd, COMMIT);
2747
 
    close_thread_tables(thd);
 
2178
    ha_autocommit_or_rollback(session, 0);
 
2179
    session->endTransaction(COMMIT);
 
2180
    session->close_thread_tables();
2748
2181
    table->table=0;                             // For query cache
2749
 
    if (protocol->write())
 
2182
    if (session->client->flush())
2750
2183
      goto err;
2751
2184
  }
2752
2185
 
2753
 
  my_eof(thd);
 
2186
  session->my_eof();
2754
2187
  return(false);
2755
2188
 
2756
2189
err:
2757
 
  ha_autocommit_or_rollback(thd, 1);
2758
 
  end_trans(thd, ROLLBACK);
2759
 
  close_thread_tables(thd);                     // Shouldn't be needed
 
2190
  ha_autocommit_or_rollback(session, 1);
 
2191
  session->endTransaction(ROLLBACK);
 
2192
  session->close_thread_tables();                       // Shouldn't be needed
2760
2193
  if (table)
2761
2194
    table->table=0;
2762
2195
  return(true);
2763
2196
}
2764
2197
 
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
 
 
2901
 
 
2902
2198
/*
2903
2199
  Create a table identical to the specified table
2904
2200
 
2905
2201
  SYNOPSIS
2906
2202
    mysql_create_like_table()
2907
 
    thd         Thread object
 
2203
    session             Thread object
2908
2204
    table       Table list element for target table
2909
2205
    src_table   Table list element for source table
2910
2206
    create_info Create info
2914
2210
    true  error
2915
2211
*/
2916
2212
 
2917
 
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
2918
 
                             HA_CREATE_INFO *create_info)
 
2213
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
 
2214
                             drizzled::message::Table& create_table_proto,
 
2215
                             drizzled::plugin::StorageEngine *engine_arg,
 
2216
                             bool is_if_not_exists,
 
2217
                             bool is_engine_set)
2919
2218
{
2920
 
  TABLE *name_lock= 0;
2921
 
  char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2922
 
  uint dst_path_length;
 
2219
  Table *name_lock= 0;
 
2220
  char src_path[FN_REFLEN];
2923
2221
  char *db= table->db;
2924
2222
  char *table_name= table->table_name;
2925
2223
  int  err;
2926
2224
  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;
 
2225
  uint32_t not_used;
 
2226
  message::Table src_proto;
 
2227
  bool lex_identified_temp_table=
 
2228
    (create_table_proto.type() == drizzled::message::Table::TEMPORARY);
2932
2229
 
2933
2230
  /*
2934
2231
    By opening source table we guarantee that it exists and no concurrent
2935
2232
    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.
 
2233
    name-lock on target table name, which makes copying of .frm cursor,
 
2234
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2235
    against concurrent DML and DDL operations on target table.
 
2236
    Thus by holding both these "locks" we ensure that our statement is
 
2237
    properly isolated from all concurrent operations which matter.
2941
2238
  */
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
 
  /* 
 
2239
  if (session->open_tables_from_list(&src_table, &not_used))
 
2240
    return true;
 
2241
 
 
2242
  strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
 
2243
 
 
2244
 
 
2245
  TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ? TEMP_TABLE : NO_TMP_TABLE);
 
2246
 
 
2247
  /*
2948
2248
    Check that destination tables does not exist. Note that its name
2949
2249
    was already checked when it was added to the table list.
2950
2250
  */
2951
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2251
  if (lex_identified_temp_table)
2952
2252
  {
2953
 
    if (find_temporary_table(thd, db, table_name))
 
2253
    if (session->find_temporary_table(db, table_name))
2954
2254
      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;
2957
2255
  }
2958
2256
  else
2959
2257
  {
2960
 
    if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
 
2258
    if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2961
2259
      goto err;
2962
 
    if (!name_lock)
 
2260
    if (! name_lock)
2963
2261
      goto table_exists;
2964
 
    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))
 
2262
 
 
2263
    if (plugin::StorageEngine::getTableDefinition(*session,
 
2264
                                                  destination_identifier) == EEXIST)
2967
2265
      goto table_exists;
2968
2266
  }
2969
2267
 
2972
2270
 
2973
2271
    Altough exclusive name-lock on target table protects us from concurrent
2974
2272
    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.
 
2273
    to plugin::StorageEngine::createTable() in critical section protected by
 
2274
    LOCK_open in order to provide minimal atomicity against operations which
 
2275
    disregard name-locks, like I_S implementation, for example. This is a
 
2276
    temporary and should not be copied. Instead we should fix our code to
 
2277
    always honor name-locks.
2979
2278
 
2980
2279
    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.
 
2280
    during the call to plugin::StorageEngine::createTable().
 
2281
    See bug #28614 for more info.
2982
2282
  */
2983
 
  VOID(pthread_mutex_lock(&LOCK_open));
2984
 
  if (src_table->schema_table)
2985
 
  {
2986
 
    if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
2987
 
    {
2988
 
      VOID(pthread_mutex_unlock(&LOCK_open));
2989
 
      goto err;
2990
 
    }
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);
 
2283
  pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2284
  {
 
2285
    int protoerr= EEXIST;
 
2286
 
 
2287
    /*
 
2288
     * If an engine was not specified and we are reading from an I_S table, then we need to toss an
 
2289
     * error. This should go away soon.
 
2290
     * @todo make this go away!
 
2291
     */
 
2292
    if (! is_engine_set)
 
2293
    {
 
2294
      string tab_name(src_path);
 
2295
      string i_s_prefix("./information_schema/");
 
2296
      if (tab_name.compare(0, i_s_prefix.length(), i_s_prefix) == 0)
 
2297
      {
 
2298
        pthread_mutex_unlock(&LOCK_open);
 
2299
        my_error(ER_ILLEGAL_HA_CREATE_OPTION,
 
2300
                 MYF(0),
 
2301
                 "INFORMATION_ENGINE",
 
2302
                 "TEMPORARY");
 
2303
        goto err;
 
2304
      }
 
2305
    }
 
2306
 
 
2307
    protoerr= plugin::StorageEngine::getTableDefinition(*session,
 
2308
                                                        src_path,
 
2309
                                                        db,
 
2310
                                                        table_name,
 
2311
                                                        false,
 
2312
                                                        &src_proto);
 
2313
 
 
2314
    message::Table new_proto(src_proto);
 
2315
 
 
2316
    if (lex_identified_temp_table)
 
2317
    {
 
2318
      new_proto.set_type(message::Table::TEMPORARY);
 
2319
    }
2996
2320
    else
2997
 
      my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2998
 
    VOID(pthread_mutex_unlock(&LOCK_open));
2999
 
    goto err;
 
2321
    {
 
2322
      new_proto.set_type(message::Table::STANDARD);
 
2323
    }
 
2324
 
 
2325
    if (is_engine_set)
 
2326
    {
 
2327
      message::Table::StorageEngine *protoengine;
 
2328
 
 
2329
      protoengine= new_proto.mutable_engine();
 
2330
      protoengine->set_name(create_table_proto.engine().name());
 
2331
    }
 
2332
 
 
2333
    if (protoerr == EEXIST)
 
2334
    {
 
2335
      plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
 
2336
                                                                       new_proto.engine().name());
 
2337
 
 
2338
      if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
 
2339
      {
 
2340
        string dst_proto_path(destination_identifier.getPath());
 
2341
        dst_proto_path.append(".dfe");
 
2342
 
 
2343
        protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
 
2344
      }
 
2345
      else
 
2346
      {
 
2347
        protoerr= 0;
 
2348
      }
 
2349
    }
 
2350
 
 
2351
    if (protoerr)
 
2352
    {
 
2353
      if (errno == ENOENT)
 
2354
        my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
2355
      else
 
2356
        my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), errno);
 
2357
      pthread_mutex_unlock(&LOCK_open);
 
2358
      goto err;
 
2359
    }
 
2360
 
 
2361
    /*
 
2362
      As mysql_truncate don't work on a new table at this stage of
 
2363
      creation, instead create the table directly (for both normal
 
2364
      and temporary tables).
 
2365
    */
 
2366
    err= plugin::StorageEngine::createTable(*session,
 
2367
                                            destination_identifier,
 
2368
                                            true, new_proto);
3000
2369
  }
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));
3012
 
 
3013
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
 
2370
  pthread_mutex_unlock(&LOCK_open);
 
2371
 
 
2372
  if (lex_identified_temp_table)
3014
2373
  {
3015
 
    if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3016
 
                                     OTM_OPEN))
 
2374
    if (err || !session->open_temporary_table(destination_identifier))
3017
2375
    {
3018
 
      (void) rm_temporary_table(create_info->db_type,
3019
 
                                dst_path, false); /* purecov: inspected */
3020
 
      goto err;     /* purecov: inspected */
 
2376
      (void) session->rm_temporary_table(engine_arg, destination_identifier);
 
2377
      goto err;
3021
2378
    }
3022
2379
  }
3023
2380
  else if (err)
3024
2381
  {
3025
 
    (void) quick_rm_table(create_info->db_type, db,
3026
 
                          table_name, 0); /* purecov: inspected */
3027
 
    goto err;       /* purecov: inspected */
 
2382
    TableIdentifier identifier(db, table_name, NO_TMP_TABLE);
 
2383
    quick_rm_table(*session, identifier);
 
2384
 
 
2385
    goto err;
3028
2386
  }
3029
2387
 
3030
2388
  /*
3031
2389
    We have to write the query before we unlock the tables.
3032
2390
  */
3033
 
  if (thd->current_stmt_binlog_row_based)
3034
2391
  {
3035
2392
    /*
3036
2393
       Since temporary tables are not replicated under row-based
3047
2404
           4    temporary temporary Nothing
3048
2405
           ==== ========= ========= ==============================
3049
2406
    */
3050
 
    if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
 
2407
    if (! lex_identified_temp_table)
3051
2408
    {
3052
2409
      if (src_table->table->s->tmp_table)               // Case 2
3053
2410
      {
3063
2420
          of this function.
3064
2421
        */
3065
2422
        table->table= name_lock;
3066
 
        VOID(pthread_mutex_lock(&LOCK_open));
3067
 
        if (reopen_name_locked_table(thd, table, false))
 
2423
        pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
 
2424
        if (session->reopen_name_locked_table(table, false))
3068
2425
        {
3069
 
          VOID(pthread_mutex_unlock(&LOCK_open));
 
2426
          pthread_mutex_unlock(&LOCK_open);
3070
2427
          goto err;
3071
2428
        }
3072
 
        VOID(pthread_mutex_unlock(&LOCK_open));
 
2429
        pthread_mutex_unlock(&LOCK_open);
3073
2430
 
3074
 
        int result= store_create_info(thd, table, &query,
3075
 
                                               create_info);
 
2431
        int result= store_create_info(table, &query, is_if_not_exists);
3076
2432
 
3077
2433
        assert(result == 0); // store_create_info() always return 0
3078
 
        write_bin_log(thd, true, query.ptr(), query.length());
 
2434
        write_bin_log(session, query.ptr(), query.length());
3079
2435
      }
3080
2436
      else                                      // Case 1
3081
 
        write_bin_log(thd, true, thd->query, thd->query_length);
 
2437
        write_bin_log(session, session->query, session->query_length);
3082
2438
    }
3083
 
    /*
3084
 
      Case 3 and 4 does nothing under RBR
3085
 
    */
3086
2439
  }
3087
 
  else
3088
 
    write_bin_log(thd, true, thd->query, thd->query_length);
3089
2440
 
3090
2441
  res= false;
3091
2442
  goto err;
3092
2443
 
3093
2444
table_exists:
3094
 
  if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
2445
  if (is_if_not_exists)
3095
2446
  {
3096
2447
    char warn_buff[DRIZZLE_ERRMSG_SIZE];
3097
2448
    snprintf(warn_buff, sizeof(warn_buff),
3098
2449
             ER(ER_TABLE_EXISTS_ERROR), table_name);
3099
 
    push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
2450
    push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3100
2451
                 ER_TABLE_EXISTS_ERROR,warn_buff);
3101
2452
    res= false;
3102
2453
  }
3106
2457
err:
3107
2458
  if (name_lock)
3108
2459
  {
3109
 
    pthread_mutex_lock(&LOCK_open);
3110
 
    unlink_open_table(thd, name_lock, false);
 
2460
    pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
 
2461
    session->unlink_open_table(name_lock);
3111
2462
    pthread_mutex_unlock(&LOCK_open);
3112
2463
  }
3113
2464
  return(res);
3114
2465
}
3115
2466
 
3116
2467
 
3117
 
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 
2468
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
3118
2469
{
3119
2470
  thr_lock_type lock_type = TL_READ_NO_INSERT;
3120
2471
 
3121
 
  return(mysql_admin_table(thd, tables, check_opt,
3122
 
                                "analyze", lock_type, 1, 0, 0, 0,
3123
 
                                &handler::ha_analyze));
 
2472
  return(mysql_admin_table(session, tables, check_opt,
 
2473
                                "analyze", lock_type, true,
 
2474
                                &Cursor::ha_analyze));
3124
2475
}
3125
2476
 
3126
2477
 
3127
 
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
 
2478
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
3128
2479
{
3129
2480
  thr_lock_type lock_type = TL_READ_NO_INSERT;
3130
2481
 
3131
 
  return(mysql_admin_table(thd, tables, check_opt,
 
2482
  return(mysql_admin_table(session, tables, check_opt,
3132
2483
                                "check", lock_type,
3133
 
                                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().
5312
 
 
5313
 
  SYNOPSIS
5314
 
    mysql_recreate_table()
5315
 
    thd                 Thread handler
5316
 
    tables              Tables to recreate
5317
 
 
5318
 
 RETURN
5319
 
    Like mysql_alter_table().
5320
 
*/
5321
 
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
5322
 
{
5323
 
  HA_CREATE_INFO create_info;
5324
 
  Alter_info alter_info;
5325
 
 
5326
 
  assert(!table_list->next_global);
5327
 
  /*
5328
 
    table_list->table has been closed and freed. Do not reference
5329
 
    uninitialized data. open_tables() could fail.
5330
 
  */
5331
 
  table_list->table= NULL;
5332
 
 
5333
 
  memset(&create_info, 0, sizeof(create_info));
5334
 
  create_info.row_type=ROW_TYPE_NOT_USED;
5335
 
  create_info.default_table_charset=default_charset_info;
5336
 
  /* 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));
5341
 
}
5342
 
 
5343
 
 
5344
 
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
5345
 
                          HA_CHECK_OPT *check_opt)
5346
 
{
5347
 
  TABLE_LIST *table;
 
2484
                                false,
 
2485
                                &Cursor::ha_check));
 
2486
}
 
2487
 
 
2488
 
 
2489
bool mysql_checksum_table(Session *session, TableList *tables,
 
2490
                          HA_CHECK_OPT *)
 
2491
{
 
2492
  TableList *table;
5348
2493
  List<Item> field_list;
5349
2494
  Item *item;
5350
 
  Protocol *protocol= thd->protocol;
5351
2495
 
5352
2496
  field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5353
2497
  item->maybe_null= 1;
5354
2498
  field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5355
2499
                                          MY_INT64_NUM_DECIMAL_DIGITS));
5356
2500
  item->maybe_null= 1;
5357
 
  if (protocol->send_fields(&field_list,
5358
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
5359
 
    return(true);
 
2501
  if (session->client->sendFields(&field_list))
 
2502
    return true;
5360
2503
 
5361
2504
  /* Open one table after the other to keep lock time as short as possible. */
5362
2505
  for (table= tables; table; table= table->next_local)
5363
2506
  {
5364
2507
    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);
 
2508
    Table *t;
 
2509
 
 
2510
    sprintf(table_name,"%s.%s",table->db,table->table_name);
 
2511
 
 
2512
    t= table->table= session->openTableLock(table, TL_READ);
 
2513
    session->clear_error();                     // these errors shouldn't get client
 
2514
 
 
2515
    session->client->store(table_name);
5374
2516
 
5375
2517
    if (!t)
5376
2518
    {
5377
2519
      /* Table didn't exist */
5378
 
      protocol->store_null();
5379
 
      thd->clear_error();
 
2520
      session->client->store();
 
2521
      session->clear_error();
5380
2522
    }
5381
2523
    else
5382
2524
    {
5383
 
      if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5384
 
          !(check_opt->flags & T_EXTEND))
5385
 
        protocol->store((uint64_t)t->file->checksum());
5386
 
      else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5387
 
               (check_opt->flags & T_QUICK))
5388
 
        protocol->store_null();
 
2525
      /**
 
2526
        @note if the engine keeps a checksum then we return the checksum, otherwise we calculate
 
2527
      */
 
2528
      if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
 
2529
      {
 
2530
        session->client->store((uint64_t)t->cursor->checksum());
 
2531
      }
5389
2532
      else
5390
2533
      {
5391
2534
        /* calculating table's checksum */
5392
2535
        ha_checksum crc= 0;
5393
 
        uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
 
2536
        unsigned char null_mask=256 -  (1 << t->s->last_null_bit_pos);
5394
2537
 
5395
2538
        t->use_all_columns();
5396
2539
 
5397
 
        if (t->file->ha_rnd_init(1))
5398
 
          protocol->store_null();
 
2540
        if (t->cursor->ha_rnd_init(1))
 
2541
          session->client->store();
5399
2542
        else
5400
2543
        {
5401
2544
          for (;;)
5402
2545
          {
5403
2546
            ha_checksum row_crc= 0;
5404
 
            int error= t->file->rnd_next(t->record[0]);
 
2547
            int error= t->cursor->rnd_next(t->record[0]);
5405
2548
            if (unlikely(error))
5406
2549
            {
5407
2550
              if (error == HA_ERR_RECORD_DELETED)
5418
2561
              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5419
2562
            }
5420
2563
 
5421
 
            for (uint i= 0; i < t->s->fields; i++ )
 
2564
            for (uint32_t i= 0; i < t->s->fields; i++ )
5422
2565
            {
5423
2566
              Field *f= t->field[i];
5424
2567
              if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5426
2569
              {
5427
2570
                String tmp;
5428
2571
                f->val_str(&tmp);
5429
 
                row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
 
2572
                row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
5430
2573
              }
5431
2574
              else
5432
2575
                row_crc= my_checksum(row_crc, f->ptr,
5435
2578
 
5436
2579
            crc+= row_crc;
5437
2580
          }
5438
 
          protocol->store((uint64_t)crc);
5439
 
          t->file->ha_rnd_end();
 
2581
          session->client->store((uint64_t)crc);
 
2582
          t->cursor->ha_rnd_end();
5440
2583
        }
5441
2584
      }
5442
 
      thd->clear_error();
5443
 
      close_thread_tables(thd);
 
2585
      session->clear_error();
 
2586
      session->close_thread_tables();
5444
2587
      table->table=0;                           // For query cache
5445
2588
    }
5446
 
    if (protocol->write())
 
2589
    if (session->client->flush())
5447
2590
      goto err;
5448
2591
  }
5449
2592
 
5450
 
  my_eof(thd);
 
2593
  session->my_eof();
5451
2594
  return(false);
5452
2595
 
5453
2596
 err:
5454
 
  close_thread_tables(thd);                     // Shouldn't be needed
 
2597
  session->close_thread_tables();                       // Shouldn't be needed
5455
2598
  if (table)
5456
2599
    table->table=0;
5457
2600
  return(true);
5458
2601
}
5459
 
 
5460
 
static bool check_engine(THD *thd, const char *table_name,
5461
 
                         HA_CREATE_INFO *create_info)
5462
 
{
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)))
5468
 
    return true;
5469
 
 
5470
 
  if (req_engine && req_engine != *new_engine)
5471
 
  {
5472
 
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5473
 
                       ER_WARN_USING_OTHER_HANDLER,
5474
 
                       ER(ER_WARN_USING_OTHER_HANDLER),
5475
 
                       ha_resolve_storage_engine_name(*new_engine),
5476
 
                       table_name);
5477
 
  }
5478
 
  if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5479
 
      ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5480
 
  {
5481
 
    if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5482
 
    {
5483
 
      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5484
 
               ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
5485
 
      *new_engine= 0;
5486
 
      return true;
5487
 
    }
5488
 
    *new_engine= myisam_hton;
5489
 
  }
5490
 
  return false;
5491
 
}