~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

Merge Monty.

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