12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
/* drop and alter of tables */
18
#include <drizzled/server_includes.h>
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/data_home.h>
24
24
#include <drizzled/sql_parse.h>
25
#include <drizzled/my_hash.h>
25
#include <mysys/hash.h>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
#include "drizzled/strfunc.h"
30
29
#include <drizzled/db.h>
31
30
#include <drizzled/lock.h>
32
31
#include <drizzled/unireg.h>
33
32
#include <drizzled/item/int.h>
34
33
#include <drizzled/item/empty_string.h>
35
#include <drizzled/transaction_services.h>
36
#include "drizzled/transaction_services.h"
34
#include <drizzled/replication_services.h>
37
35
#include <drizzled/table_proto.h>
38
36
#include <drizzled/plugin/client.h>
39
#include <drizzled/identifier.h>
40
#include "drizzled/internal/m_string.h"
41
#include "drizzled/global_charset_info.h"
42
#include "drizzled/charset.h"
44
#include "drizzled/definition/cache.h"
47
#include "drizzled/statement/alter_table.h"
48
#include "drizzled/sql_table.h"
49
#include "drizzled/pthread_globals.h"
38
#include "drizzled/statement/alter_table.h" /* for mysql_create_like_schema_frm, which will die soon */
51
40
#include <algorithm>
54
#include <boost/unordered_set.hpp>
56
42
using namespace std;
61
extern pid_t current_pid;
63
bool is_primary_key(KeyInfo *key_info)
43
using namespace drizzled;
45
static const char hexchars[]= "0123456789abcdef";
46
bool is_primary_key(KEY *key_info)
65
48
static const char * primary_key_name="PRIMARY";
66
49
return (strcmp(key_info->name, primary_key_name)==0);
78
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
79
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
61
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
62
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
81
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
83
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
66
void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
86
69
If the table character set was not given explicitly,
87
70
let's fetch the database default character set and
88
71
apply it to the table.
90
SchemaIdentifier identifier(db);
91
73
if (create_info->default_table_charset == NULL)
92
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
74
create_info->default_table_charset= get_default_db_collation(db);
78
Translate a file name to a table name (WL #1324).
81
filename_to_tablename()
84
to_length The size of the table name buffer.
89
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
93
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
95
/* Temporary table name. */
96
length= strlen(strncpy(to, from, to_length));
100
for (; *from && length < to_length; length++, from++)
107
/* We've found an escaped char - skip the @ */
110
/* There will be a two-position hex-char version of the char */
111
for (int x=1; x >= 0; x--)
113
if (*from >= '0' && *from <= '9')
114
to[length] += ((*from++ - '0') << (4 * x));
115
else if (*from >= 'a' && *from <= 'f')
116
to[length] += ((*from++ - 'a' + 10) << (4 * x));
118
/* Backup because we advanced extra in the inner loop */
128
Translate a table name to a file name (WL #1324).
131
tablename_to_filename()
134
to_length The size of the file name buffer.
137
true if errors happen. false on success.
139
bool tablename_to_filename(const char *from, char *to, size_t to_length)
143
for (; *from && length < to_length; length++, from++)
145
if ((*from >= '0' && *from <= '9') ||
146
(*from >= 'A' && *from <= 'Z') ||
147
(*from >= 'a' && *from <= 'z') ||
148
/* OSX defines an extra set of high-bit and multi-byte characters
149
that cannot be used on the filesystem. Instead of trying to sort
150
those out, we'll just escape encode all high-bit-set chars on OSX.
151
It won't really hurt anything - it'll just make some filenames ugly. */
152
#if !defined(TARGET_OS_OSX)
153
((unsigned char)*from >= 128) ||
163
if (length + 3 >= to_length)
166
/* We need to escape this char in a way that can be reversed */
168
to[length++]= hexchars[(*from >> 4) & 15];
169
to[length]= hexchars[(*from) & 15];
172
if (check_if_legal_tablename(to) &&
173
length + 4 < to_length)
175
memcpy(to + length, "@@@", 4);
183
Creates path to a file: drizzle_data_dir/db/table.ext
186
build_table_filename()
187
buff Where to write result
188
This may be the same as table_name.
191
table_name Table name
193
flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
194
table_name is temporary, do not change.
198
Uses database and table name, and extension to create
199
a file name in drizzle_data_dir. Database and table
200
names are converted from system_charset_info into "fscs".
201
Unless flags indicate a temporary table name.
202
'db' is always converted.
203
'ext' is not converted.
205
The conversion suppression is required for ALTER Table. This
206
statement creates intermediate tables. These are regular
207
(non-temporary) tables with a temporary name. Their path names must
208
be derivable from the table name. So we cannot use
209
build_tmptable_filename() for them.
212
path length on success, 0 on failure
215
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
217
char dbbuff[FN_REFLEN];
218
char tbbuff[FN_REFLEN];
219
bool conversion_error= false;
221
memset(tbbuff, 0, sizeof(tbbuff));
222
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
223
strncpy(tbbuff, table_name, sizeof(tbbuff));
226
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
227
if (conversion_error)
229
errmsg_printf(ERRMSG_LVL_ERROR,
230
_("Table name cannot be encoded and fit within filesystem "
231
"name length restrictions."));
235
memset(dbbuff, 0, sizeof(dbbuff));
236
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
237
if (conversion_error)
239
errmsg_printf(ERRMSG_LVL_ERROR,
240
_("Schema name cannot be encoded and fit within filesystem "
241
"name length restrictions."));
246
int rootdir_len= strlen(FN_ROOTDIR);
247
string table_path(drizzle_data_home);
248
int without_rootdir= table_path.length()-rootdir_len;
250
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
251
if (without_rootdir >= 0)
253
const char *tmp= table_path.c_str()+without_rootdir;
254
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
255
table_path.append(FN_ROOTDIR);
258
table_path.append(dbbuff);
259
table_path.append(FN_ROOTDIR);
260
table_path.append(tbbuff);
262
if (bufflen < table_path.length())
265
strcpy(buff, table_path.c_str());
267
return table_path.length();
272
Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
275
build_tmptable_filename()
276
session The thread handle.
277
buff Where to write result
282
Uses current_pid, thread_id, and tmp_table counter to create
283
a file name in drizzle_tmpdir.
286
path length on success, 0 on failure
289
static uint32_t build_tmptable_filename(Session* session,
290
char *buff, size_t bufflen)
293
ostringstream path_str, post_tmpdir_str;
296
path_str << drizzle_tmpdir;
297
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
298
post_tmpdir_str << session->thread_id << session->tmp_table++;
299
tmp= post_tmpdir_str.str();
301
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
305
if (bufflen < path_str.str().length())
308
length= unpack_filename(buff, path_str.str().c_str());
106
324
Write the binlog if open, routine used in multiple places in this
110
void write_bin_log(Session *session, const std::string &query)
112
TransactionServices &transaction_services= TransactionServices::singleton();
113
transaction_services.rawStatement(session, query);
328
void write_bin_log(Session *session,
329
char const *query, size_t query_length)
331
ReplicationServices &replication_services= ReplicationServices::singleton();
332
replication_services.rawStatement(session, query, query_length);
336
/* Should should be refactored to go away */
337
static void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
339
ReplicationServices &replication_services= ReplicationServices::singleton();
343
built_query.append("DROP Table IF EXISTS ");
345
built_query.append("DROP Table ");
347
built_query.append("`");
348
if (session->db == NULL || strcmp(db_name ,session->db) != 0)
350
built_query.append(db_name);
351
built_query.append("`.`");
354
built_query.append(table_name);
355
built_query.append("`");
356
replication_services.rawStatement(session, built_query.c_str(), built_query.length());
361
delete (drop) tables.
365
session Thread handle
366
tables List of tables to delete
367
if_exists If 1, don't give error if one table doesn't exists
370
Will delete all tables that can be deleted and give a compact error
371
messages for tables that could not be deleted.
372
If a table is in use, we will wait for all users to free the table
375
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
376
not if under LOCK TABLES.
379
false OK. In this case ok packet is sent to user
384
bool mysql_rm_table(Session *session,TableList *tables, bool if_exists, bool drop_temporary)
386
bool error, need_start_waiting= false;
388
if (tables && tables->schema_table)
390
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
394
/* mark for close and remove all cached entries */
398
if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
403
Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
404
LOCK_open during wait_if_global_read_lock(), other threads could not
405
close their tables. This would make a pretty deadlock.
407
error= mysql_rm_table_part2(session, tables, if_exists, drop_temporary, false);
409
if (need_start_waiting)
410
start_waiting_global_read_lock(session);
143
447
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
448
bool drop_temporary, bool dont_log_query)
146
450
TableList *table;
451
char path[FN_REFLEN];
452
uint32_t path_length= 0;
147
453
String wrong_tables;
149
455
bool foreign_key_error= false;
152
table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
154
if (not drop_temporary && session->lock_table_names_exclusively(tables))
156
table::Cache::singleton().mutex().unlock();
160
/* Don't give warnings for not found errors, as we already generate notes */
161
session->no_warnings_for_error= 1;
163
for (table= tables; table; table= table->next_local)
165
TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
167
error= session->drop_temporary_table(tmp_identifier);
171
// removed temporary table
457
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
460
If we have the table in the definition cache, we don't have to check the
461
.frm file to find if the table is a normal table (not view) and what
465
for (table= tables; table; table= table->next_local)
468
table->db_type= NULL;
469
if ((share= TableShare::getShare(table->db, table->table_name)))
470
table->db_type= share->db_type();
473
if (!drop_temporary && lock_table_names_exclusively(session, tables))
475
pthread_mutex_unlock(&LOCK_open);
479
/* Don't give warnings for not found errors, as we already generate notes */
480
session->no_warnings_for_error= 1;
482
for (table= tables; table; table= table->next_local)
485
plugin::StorageEngine *table_type;
487
error= session->drop_temporary_table(table);
491
// removed temporary table
495
goto err_with_placeholders;
497
// temporary table not found
501
table_type= table->db_type;
505
abort_locked_tables(session, db, table->table_name);
506
remove_table_from_cache(session, db, table->table_name,
507
RTFC_WAIT_OTHER_THREAD_FLAG |
508
RTFC_CHECK_KILLED_FLAG);
510
If the table was used in lock tables, remember it so that
511
unlock_table_names can free it
513
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
514
table->table= locked_table;
519
goto err_with_placeholders;
521
/* remove .frm file and engine files */
522
path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
525
if (drop_temporary ||
527
&& (plugin::StorageEngine::getTableProto(path, NULL) != EEXIST))))
529
// Table was not found on disk and table can't be created from engine
531
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
532
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
175
goto err_with_placeholders;
177
// temporary table not found
181
if (drop_temporary == false)
184
abort_locked_tables(session, tmp_identifier);
185
table::Cache::singleton().removeTable(session, tmp_identifier,
186
RTFC_WAIT_OTHER_THREAD_FLAG |
187
RTFC_CHECK_KILLED_FLAG);
189
If the table was used in lock tables, remember it so that
190
unlock_table_names can free it
192
if ((locked_table= drop_locked_tables(session, tmp_identifier)))
193
table->table= locked_table;
195
if (session->getKilled())
198
goto err_with_placeholders;
201
TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
203
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
205
// Table was not found on disk and table can't be created from engine
207
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
208
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
209
table->getTableName());
215
error= plugin::StorageEngine::dropTable(*session, identifier);
217
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
220
session->clear_error();
223
if (error == HA_ERR_ROW_IS_REFERENCED)
225
/* the table is referenced by a foreign key constraint */
226
foreign_key_error= true;
230
if (error == 0 || (if_exists && foreign_key_error == false))
232
TransactionServices &transaction_services= TransactionServices::singleton();
233
transaction_services.dropTable(session, string(table->getSchemaName()), string(table->getTableName()), if_exists);
238
if (wrong_tables.length())
239
wrong_tables.append(',');
240
wrong_tables.append(String(table->getTableName(), system_charset_info));
244
It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
247
table::Cache::singleton().mutex().unlock();
539
error= plugin::StorageEngine::deleteTable(session, path, db,
542
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
545
session->clear_error();
548
if (error == HA_ERR_ROW_IS_REFERENCED)
550
/* the table is referenced by a foreign key constraint */
551
foreign_key_error= true;
555
if (error == 0 || (if_exists && foreign_key_error == false))
556
write_bin_log_drop_table(session, if_exists, db, table->table_name);
560
if (wrong_tables.length())
561
wrong_tables.append(',');
562
wrong_tables.append(String(table->table_name,system_charset_info));
566
It's safe to unlock LOCK_open: we have an exclusive lock
569
pthread_mutex_unlock(&LOCK_open);
251
571
if (wrong_tables.length())
253
if (not foreign_key_error)
573
if (!foreign_key_error)
255
574
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
575
wrong_tables.c_ptr());
260
578
my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
1267
static bool locked_create_event(Session *session,
1268
const TableIdentifier &identifier,
1269
HA_CREATE_INFO *create_info,
1270
message::Table &table_proto,
1271
AlterInfo *alter_info,
1272
bool is_if_not_exists,
1273
bool internal_tmp_table,
1276
KeyInfo *key_info_buffer)
1283
@note if we are building a temp table we need to check to see if a temp table
1284
already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1285
to create a table under a temporary table.
1288
plugin::StorageEngine::doesTableExist(*session, identifier,
1289
identifier.getType() != message::Table::STANDARD );
1293
if (is_if_not_exists)
1296
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1297
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1298
identifier.getTableName().c_str());
1299
create_info->table_existed= 1; // Mark that table existed
1304
identifier.getSQLPath(path);
1305
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1310
if (identifier.getType() == message::Table::STANDARD) // We have a real table
1313
We don't assert here, but check the result, because the table could be
1314
in the table definition cache and in the same time the .frm could be
1315
missing from the disk, in case of manual intervention which deletes
1316
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1317
Then she could create the table. This case is pretty obscure and
1318
therefore we don't introduce a new error message only for it.
1321
@todo improve this error condition.
1323
if (definition::Cache::singleton().find(identifier.getKey()))
1326
identifier.getSQLPath(path);
1327
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1334
session->set_proc_info("creating table");
1335
create_info->table_existed= 0; // Mark that table is created
1337
create_info->table_options= db_options;
1339
if (not rea_create_table(session, identifier,
1341
create_info, alter_info->create_list,
1342
key_count, key_info_buffer))
1347
if (identifier.getType() == message::Table::TEMPORARY)
1349
/* Open table and put in temporary table list */
1350
if (not (session->open_temporary_table(identifier)))
1352
(void) session->rm_temporary_table(identifier);
1358
We keep this behind the lock to make sure ordering is correct for a table.
1359
This is a very unlikely problem where before we would write out to the
1360
trans log, someone would do a delete/create operation.
1363
if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1365
TransactionServices &transaction_services= TransactionServices::singleton();
1366
transaction_services.createTable(session, table_proto);
1374
1559
Ignore the name of this function... it locks :(
1403
1588
bool mysql_create_table_no_lock(Session *session,
1404
const TableIdentifier &identifier,
1589
const char *db, const char *table_name,
1405
1590
HA_CREATE_INFO *create_info,
1406
message::Table &table_proto,
1591
message::Table *table_proto,
1407
1592
AlterInfo *alter_info,
1408
1593
bool internal_tmp_table,
1409
uint32_t select_field_count,
1410
bool is_if_not_exists)
1594
uint32_t select_field_count)
1596
char path[FN_REFLEN];
1597
uint32_t path_length;
1412
1598
uint db_options, key_count;
1413
KeyInfo *key_info_buffer;
1599
KEY *key_info_buffer;
1414
1601
bool error= true;
1416
1602
/* Check for duplicate fields and check type of table to create */
1417
if (not alter_info->create_list.elements)
1603
if (!alter_info->create_list.elements)
1419
1605
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1423
assert(identifier.getTableName() == table_proto.name());
1609
assert(strcmp(table_name,table_proto->name().c_str())==0);
1610
if (check_engine(session, table_name, create_info))
1424
1612
db_options= create_info->table_options;
1426
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1428
/* Build a Table object to pass down to the engine, and the do the actual create. */
1429
if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1432
&key_info_buffer, &key_count,
1433
select_field_count))
1435
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1436
error= locked_create_event(session,
1443
db_options, key_count,
1447
session->set_proc_info("After create");
1453
@note the following two methods implement create [temporary] table.
1455
static bool drizzle_create_table(Session *session,
1456
const TableIdentifier &identifier,
1457
HA_CREATE_INFO *create_info,
1458
message::Table &table_proto,
1459
AlterInfo *alter_info,
1460
bool internal_tmp_table,
1461
uint32_t select_field_count,
1462
bool is_if_not_exists)
1464
Table *name_lock= NULL;
1467
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1471
else if (name_lock == NULL)
1473
if (is_if_not_exists)
1613
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1614
db_options|=HA_OPTION_PACK_RECORD;
1615
if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
1616
create_info->db_type)))
1618
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1622
set_table_default_charset(create_info, (char*) db);
1624
if (mysql_prepare_create_table(session, create_info, alter_info,
1627
&key_info_buffer, &key_count,
1628
select_field_count))
1631
/* Check if table exists */
1632
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1634
path_length= build_tmptable_filename(session, path, sizeof(path));
1639
/* check if the table name contains FN_DEVCHAR when defined */
1640
if (strchr(table_name, FN_DEVCHAR))
1642
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
1646
path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
1649
/* Check if table already exists */
1650
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1651
session->find_temporary_table(db, table_name))
1653
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1655
create_info->table_existed= 1; // Mark that table existed
1475
1656
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1476
1657
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1477
identifier.getTableName().c_str());
1478
create_info->table_existed= 1;
1484
identifier.getSQLPath(path);
1485
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1491
result= mysql_create_table_no_lock(session,
1503
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1504
session->unlink_open_table(name_lock);
1662
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1666
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1667
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1669
if (plugin::StorageEngine::getTableProto(path, NULL)==EEXIST)
1671
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1674
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1675
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1677
create_info->table_existed= 1; // Mark that table existed
1680
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1682
goto unlock_and_end;
1685
We don't assert here, but check the result, because the table could be
1686
in the table definition cache and in the same time the .frm could be
1687
missing from the disk, in case of manual intervention which deletes
1688
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1689
Then she could create the table. This case is pretty obscure and
1690
therefore we don't introduce a new error message only for it.
1692
if (TableShare::getShare(db, table_name))
1694
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1695
goto unlock_and_end;
1700
Check that table with given name does not already
1701
exist in any storage engine. In such a case it should
1702
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1703
unless user specified CREATE TABLE IF EXISTS
1704
The LOCK_open mutex has been locked to make sure no
1705
one else is attempting to discover the table. Since
1706
it's not on disk as a frm file, no one could be using it!
1708
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1710
bool create_if_not_exists =
1711
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1713
char table_path[FN_REFLEN];
1714
uint32_t table_path_length;
1716
table_path_length= build_table_filename(table_path, sizeof(table_path),
1717
db, table_name, false);
1719
int retcode= plugin::StorageEngine::getTableProto(table_path, NULL);
1723
/* Normal case, no table exists. we can go and create it */
1726
if (create_if_not_exists)
1729
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1730
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1732
create_info->table_existed= 1; // Mark that table existed
1733
goto unlock_and_end;
1735
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1736
goto unlock_and_end;
1738
my_error(retcode, MYF(0),table_name);
1739
goto unlock_and_end;
1743
session->set_proc_info("creating table");
1744
create_info->table_existed= 0; // Mark that table is created
1746
create_info->table_options=db_options;
1748
if (rea_create_table(session, path, db, table_name,
1750
create_info, alter_info->create_list,
1751
key_count, key_info_buffer))
1752
goto unlock_and_end;
1754
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1756
/* Open table and put in temporary table list */
1757
if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
1759
(void) session->rm_temporary_table(create_info->db_type, path);
1760
goto unlock_and_end;
1765
Don't write statement if:
1766
- It is an internal temporary table,
1767
- Row-based logging is used and it we are creating a temporary table, or
1768
- The binary log is not open.
1769
Otherwise, the statement shall be binlogged.
1771
if (!internal_tmp_table &&
1772
((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1773
write_bin_log(session, session->query, session->query_length);
1776
pthread_mutex_unlock(&LOCK_open);
1779
session->set_proc_info("After create");
1512
1786
Database locking aware wrapper for mysql_create_table_no_lock(),
1514
bool mysql_create_table(Session *session,
1515
const TableIdentifier &identifier,
1789
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1516
1790
HA_CREATE_INFO *create_info,
1517
message::Table &table_proto,
1791
message::Table *table_proto,
1518
1792
AlterInfo *alter_info,
1519
1793
bool internal_tmp_table,
1520
uint32_t select_field_count,
1521
bool is_if_not_exists)
1794
uint32_t select_field_count)
1523
if (identifier.isTmp())
1525
return mysql_create_table_no_lock(session,
1535
return drizzle_create_table(session,
1796
Table *name_lock= NULL;
1799
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1801
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
1806
if (name_lock == NULL)
1808
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1810
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1811
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1813
create_info->table_existed= 1;
1818
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1825
result= mysql_create_table_no_lock(session, db, table_name, create_info,
1829
select_field_count);
1834
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1835
session->unlink_open_table(name_lock);
1836
pthread_mutex_unlock(&LOCK_open);
1609
mysql_rename_table(Session &session,
1610
plugin::StorageEngine *base,
1611
const TableIdentifier &from,
1612
const TableIdentifier &to)
1910
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
1911
const char *old_name, const char *new_db,
1912
const char *new_name, uint32_t flags)
1914
Session *session= current_session;
1915
char from[FN_REFLEN], to[FN_REFLEN];
1916
char *from_base= from, *to_base= to;
1618
if (not plugin::StorageEngine::doesSchemaExist(to))
1921
build_table_filename(from, sizeof(from), old_db, old_name,
1922
flags & FN_FROM_IS_TMP);
1923
build_table_filename(to, sizeof(to), new_db, new_name,
1924
flags & FN_TO_IS_TMP);
1926
if (!(error=base->renameTable(session, from_base, to_base)))
1620
my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1928
if(!(flags & NO_FRM_RENAME)
1929
&& base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
1930
&& rename_table_proto_file(from_base, to_base))
1933
base->renameTable(session, to_base, from_base);
1624
error= base->renameTable(session, from, to);
1626
1937
if (error == HA_ERR_WRONG_COMMAND)
1628
1938
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1630
1939
else if (error)
1632
std::string from_path;
1633
std::string to_path;
1635
from.getSQLPath(from_path);
1636
to.getSQLPath(to_path);
1638
const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1639
const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1641
my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1644
return error ? true : false;
1940
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
1901
2235
session->client->store(STRING_WITH_LEN("Invalid argument"));
2238
case HA_ADMIN_TRY_ALTER:
2241
This is currently used only by InnoDB. ha_innobase::optimize() answers
2242
"try with alter", so here we close the table, do an ALTER Table,
2243
reopen the table and do ha_innobase::analyze() on it.
2245
ha_autocommit_or_rollback(session, 0);
2246
session->close_thread_tables();
2247
TableList *save_next_local= table->next_local,
2248
*save_next_global= table->next_global;
2249
table->next_local= table->next_global= 0;
2250
result_code= mysql_recreate_table(session, table);
2252
mysql_recreate_table() can push OK or ERROR.
2253
Clear 'OK' status. If there is an error, keep it:
2254
we will store the error message in a result set row
2257
if (session->main_da.is_ok())
2258
session->main_da.reset_diagnostics_area();
2259
ha_autocommit_or_rollback(session, 0);
2260
session->close_thread_tables();
2261
if (!result_code) // recreation went ok
2263
if ((table->table= session->openTableLock(table, lock_type)) &&
2264
((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
2265
result_code= 0; // analyze went ok
2267
if (result_code) // either mysql_recreate_table or analyze failed
2269
assert(session->is_error());
2270
if (session->is_error())
2272
const char *err_msg= session->main_da.message();
2273
/* Hijack the row already in-progress. */
2274
session->client->store(STRING_WITH_LEN("error"));
2275
session->client->store(err_msg);
2276
(void)session->client->flush();
2277
/* Start off another row for HA_ADMIN_FAILED */
2278
session->client->store(table_name);
2279
session->client->store(operator_name);
2280
session->clear_error();
2283
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
2284
table->next_local= save_next_local;
2285
table->next_global= save_next_global;
2286
goto send_result_message;
2288
case HA_ADMIN_NEEDS_UPGRADE:
2289
case HA_ADMIN_NEEDS_ALTER:
2291
char buf[ERRMSGSIZE];
2294
session->client->store(STRING_WITH_LEN("error"));
2295
length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
2296
session->client->store(buf, length);
1904
2301
default: // Probably HA_ADMIN_INTERNAL_ERROR
1906
2303
char buf[ERRMSGSIZE+20];
1957
Create a new table by copying from source table
1959
Altough exclusive name-lock on target table protects us from concurrent
1960
DML and DDL operations on it we still want to wrap .FRM creation and call
1961
to plugin::StorageEngine::createTable() in critical section protected by
1962
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1963
disregard name-locks, like I_S implementation, for example. This is a
1964
temporary and should not be copied. Instead we should fix our code to
1965
always honor name-locks.
1967
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1968
during the call to plugin::StorageEngine::createTable().
1969
See bug #28614 for more info.
1971
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
const TableIdentifier &destination_identifier,
1973
const TableIdentifier &src_table,
2350
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
1976
int protoerr= EEXIST;
1977
message::Table new_proto;
1978
message::table::shared_ptr src_proto;
1980
protoerr= plugin::StorageEngine::getTableDefinition(session,
1983
new_proto.CopyFrom(*src_proto);
1985
if (destination_identifier.isTmp())
1987
new_proto.set_type(message::Table::TEMPORARY);
1991
new_proto.set_type(message::Table::STANDARD);
1996
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
1999
{ // We now do a selective copy of elements on to the new table.
2000
new_proto.set_name(create_table_proto.name());
2001
new_proto.set_schema(create_table_proto.schema());
2002
new_proto.set_catalog(create_table_proto.catalog());
2005
if (protoerr && protoerr != EEXIST)
2007
if (errno == ENOENT)
2008
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2010
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2016
As mysql_truncate don't work on a new table at this stage of
2017
creation, instead create the table directly (for both normal
2018
and temporary tables).
2020
int err= plugin::StorageEngine::createTable(session,
2021
destination_identifier,
2024
if (err == false && not destination_identifier.isTmp())
2026
TransactionServices &transaction_services= TransactionServices::singleton();
2027
transaction_services.createTable(&session, new_proto);
2030
return err ? false : true;
2352
return(mysql_admin_table(session, tables, check_opt,
2353
"optimize", TL_WRITE, 1,0,0,0,
2354
&handler::ha_optimize));
2048
bool mysql_create_like_table(Session* session,
2049
const TableIdentifier &destination_identifier,
2050
TableList* table, TableList* src_table,
2051
message::Table &create_table_proto,
2052
bool is_if_not_exists,
2372
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2373
drizzled::message::Table& create_table_proto,
2374
HA_CREATE_INFO *create_info)
2376
Table *name_lock= 0;
2377
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2378
uint32_t dst_path_length;
2379
char *db= table->db;
2380
char *table_name= table->table_name;
2055
2382
bool res= true;
2056
2383
uint32_t not_used;
2384
message::Table src_proto;
2059
2387
By opening source table we guarantee that it exists and no concurrent
2060
2388
DDL operation will mess with it. Later we also take an exclusive
2061
name-lock on target table name, which makes copying of .frm cursor,
2062
call to plugin::StorageEngine::createTable() and binlogging atomic
2063
against concurrent DML and DDL operations on target table.
2064
Thus by holding both these "locks" we ensure that our statement is
2065
properly isolated from all concurrent operations which matter.
2389
name-lock on target table name, which makes copying of .frm file,
2390
call to StorageEngine::createTable() and binlogging atomic against concurrent DML
2391
and DDL operations on target table. Thus by holding both these "locks"
2392
we ensure that our statement is properly isolated from all concurrent
2393
operations which matter.
2067
2395
if (session->open_tables_from_list(&src_table, ¬_used))
2070
TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2071
src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2398
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2076
2402
Check that destination tables does not exist. Note that its name
2077
2403
was already checked when it was added to the table list.
2079
For temporary tables we don't aim to grab locks.
2081
bool table_exists= false;
2082
if (destination_identifier.isTmp())
2084
if (session->find_temporary_table(destination_identifier))
2090
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
src_identifier, is_engine_set);
2092
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2094
(void) session->rm_temporary_table(destination_identifier, true);
2096
else if (not session->open_temporary_table(destination_identifier))
2098
// We created, but we can't open... also, a hack.
2099
(void) session->rm_temporary_table(destination_identifier, true);
2107
else // Standard table which will require locks.
2109
Table *name_lock= 0;
2111
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2115
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2116
session->unlink_open_table(name_lock);
2126
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2130
else // Otherwise we create the table
2134
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2135
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2136
src_identifier, is_engine_set);
2139
// So we blew the creation of the table, and we scramble to clean up
2140
// anything that might have been created (read... it is a hack)
2141
if (not was_created)
2143
plugin::StorageEngine::dropTable(*session, destination_identifier);
2153
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2154
session->unlink_open_table(name_lock);
2160
if (is_if_not_exists)
2162
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
snprintf(warn_buff, sizeof(warn_buff),
2164
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2165
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2166
ER_TABLE_EXISTS_ERROR,warn_buff);
2171
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2405
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2407
if (session->find_temporary_table(db, table_name))
2409
dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2413
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2417
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2418
db, table_name, false);
2419
if (plugin::StorageEngine::getTableProto(dst_path, NULL) == EEXIST)
2424
Create a new table by copying from source table
2426
Altough exclusive name-lock on target table protects us from concurrent
2427
DML and DDL operations on it we still want to wrap .FRM creation and call
2428
to StorageEngine::createTable() in critical section protected by LOCK_open in order
2429
to provide minimal atomicity against operations which disregard name-locks,
2430
like I_S implementation, for example. This is a temporary and should not
2431
be copied. Instead we should fix our code to always honor name-locks.
2433
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2434
during the call to StorageEngine::createTable(). See bug #28614 for more info.
2436
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2438
int protoerr= EEXIST;
2440
if (src_table->schema_table)
2442
if (mysql_create_like_schema_frm(session, src_table, create_info,
2445
pthread_mutex_unlock(&LOCK_open);
2451
protoerr= plugin::StorageEngine::getTableProto(src_path, &src_proto);
2454
message::Table new_proto(src_proto);
2456
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
2458
message::Table::StorageEngine *protoengine;
2460
protoengine= new_proto.mutable_engine();
2461
protoengine->set_name(create_table_proto.engine().name());
2464
string dst_proto_path(dst_path);
2465
string file_ext = ".dfe";
2467
dst_proto_path.append(file_ext);
2469
if (protoerr == EEXIST)
2471
plugin::StorageEngine* engine= plugin::StorageEngine::findByName(session,
2472
new_proto.engine().name());
2474
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2475
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
2482
if (my_errno == ENOENT)
2483
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2485
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2486
pthread_mutex_unlock(&LOCK_open);
2491
As mysql_truncate don't work on a new table at this stage of
2492
creation, instead create the table directly (for both normal
2493
and temporary tables).
2495
err= plugin::StorageEngine::createTable(session, dst_path, db, table_name, create_info,
2498
pthread_mutex_unlock(&LOCK_open);
2500
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2502
if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
2504
(void) session->rm_temporary_table(create_info->db_type, dst_path);
2510
(void) quick_rm_table(create_info->db_type, db,
2516
We have to write the query before we unlock the tables.
2520
Since temporary tables are not replicated under row-based
2521
replication, CREATE TABLE ... LIKE ... needs special
2522
treatement. We have four cases to consider, according to the
2523
following decision table:
2525
==== ========= ========= ==============================
2526
Case Target Source Write to binary log
2527
==== ========= ========= ==============================
2528
1 normal normal Original statement
2529
2 normal temporary Generated statement
2530
3 temporary normal Nothing
2531
4 temporary temporary Nothing
2532
==== ========= ========= ==============================
2534
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2536
if (src_table->table->s->tmp_table) // Case 2
2539
String query(buf, sizeof(buf), system_charset_info);
2540
query.length(0); // Have to zero it since constructor doesn't
2544
Here we open the destination table, on which we already have
2545
name-lock. This is needed for store_create_info() to work.
2546
The table will be closed by unlink_open_table() at the end
2549
table->table= name_lock;
2550
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2551
if (session->reopen_name_locked_table(table, false))
2553
pthread_mutex_unlock(&LOCK_open);
2556
pthread_mutex_unlock(&LOCK_open);
2558
int result= store_create_info(table, &query, create_info);
2560
assert(result == 0); // store_create_info() always return 0
2561
write_bin_log(session, query.ptr(), query.length());
2564
write_bin_log(session, session->query, session->query_length);
2572
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2574
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2575
snprintf(warn_buff, sizeof(warn_buff),
2576
ER(ER_TABLE_EXISTS_ERROR), table_name);
2577
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2578
ER_TABLE_EXISTS_ERROR,warn_buff);
2582
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2587
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2588
session->unlink_open_table(name_lock);
2589
pthread_mutex_unlock(&LOCK_open);
2193
2609
return(mysql_admin_table(session, tables, check_opt,
2194
2610
"check", lock_type,
2196
&Cursor::ha_check));
2199
} /* namespace drizzled */
2611
0, 0, HA_OPEN_FOR_REPAIR, 0,
2612
&handler::ha_check));
2616
Recreates tables by calling mysql_alter_table().
2619
mysql_recreate_table()
2620
session Thread handler
2621
tables Tables to recreate
2624
Like mysql_alter_table().
2626
bool mysql_recreate_table(Session *session, TableList *table_list)
2628
HA_CREATE_INFO create_info;
2629
AlterInfo alter_info;
2630
message::Table table_proto;
2632
assert(!table_list->next_global);
2634
table_list->table has been closed and freed. Do not reference
2635
uninitialized data. open_tables() could fail.
2637
table_list->table= NULL;
2639
memset(&create_info, 0, sizeof(create_info));
2640
create_info.row_type=ROW_TYPE_NOT_USED;
2641
create_info.default_table_charset=default_charset_info;
2642
/* Force alter table to recreate table */
2643
alter_info.flags.set(ALTER_CHANGE_COLUMN);
2644
alter_info.flags.set(ALTER_RECREATE);
2645
return(mysql_alter_table(session, NULL, NULL, &create_info, &table_proto,
2646
table_list, &alter_info, 0,
2647
(order_st *) 0, 0));
2651
bool mysql_checksum_table(Session *session, TableList *tables,
2652
HA_CHECK_OPT *check_opt)
2655
List<Item> field_list;
2658
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2659
item->maybe_null= 1;
2660
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2661
MY_INT64_NUM_DECIMAL_DIGITS));
2662
item->maybe_null= 1;
2663
if (session->client->sendFields(&field_list))
2666
/* Open one table after the other to keep lock time as short as possible. */
2667
for (table= tables; table; table= table->next_local)
2669
char table_name[NAME_LEN*2+2];
2672
sprintf(table_name,"%s.%s",table->db,table->table_name);
2674
t= table->table= session->openTableLock(table, TL_READ);
2675
session->clear_error(); // these errors shouldn't get client
2677
session->client->store(table_name);
2681
/* Table didn't exist */
2682
session->client->store();
2683
session->clear_error();
2687
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
2688
!(check_opt->flags & T_EXTEND))
2689
session->client->store((uint64_t)t->file->checksum());
2690
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
2691
(check_opt->flags & T_QUICK))
2692
session->client->store();
2695
/* calculating table's checksum */
2697
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2699
t->use_all_columns();
2701
if (t->file->ha_rnd_init(1))
2702
session->client->store();
2707
ha_checksum row_crc= 0;
2708
int error= t->file->rnd_next(t->record[0]);
2709
if (unlikely(error))
2711
if (error == HA_ERR_RECORD_DELETED)
2715
if (t->s->null_bytes)
2717
/* fix undefined null bits */
2718
t->record[0][t->s->null_bytes-1] |= null_mask;
2719
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2720
t->record[0][0] |= 1;
2722
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2725
for (uint32_t i= 0; i < t->s->fields; i++ )
2727
Field *f= t->field[i];
2728
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2729
(f->type() == DRIZZLE_TYPE_VARCHAR))
2733
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2736
row_crc= my_checksum(row_crc, f->ptr,
2742
session->client->store((uint64_t)crc);
2743
t->file->ha_rnd_end();
2746
session->clear_error();
2747
session->close_thread_tables();
2748
table->table=0; // For query cache
2750
if (session->client->flush())
2758
session->close_thread_tables(); // Shouldn't be needed
2764
bool check_engine(Session *session, const char *table_name,
2765
HA_CREATE_INFO *create_info)
2767
plugin::StorageEngine **new_engine= &create_info->db_type;
2768
plugin::StorageEngine *req_engine= *new_engine;
2769
if (!req_engine->is_enabled())
2771
string engine_name= req_engine->getName();
2772
my_error(ER_FEATURE_DISABLED,MYF(0),
2773
engine_name.c_str(), engine_name.c_str());
2778
if (req_engine && req_engine != *new_engine)
2780
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2781
ER_WARN_USING_OTHER_HANDLER,
2782
ER(ER_WARN_USING_OTHER_HANDLER),
2783
plugin::StorageEngine::resolveName(*new_engine).c_str(),
2786
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
2787
(*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
2789
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
2791
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2792
plugin::StorageEngine::resolveName(*new_engine).c_str(),
2797
*new_engine= myisam_engine;
2799
if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
2800
&& (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
2802
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2803
plugin::StorageEngine::resolveName(*new_engine).c_str(),