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"
37
#include <drizzled/table_identifier.h>
47
39
#include "drizzled/statement/alter_table.h"
48
#include "drizzled/sql_table.h"
49
#include "drizzled/pthread_globals.h"
40
#include "drizzled/plugin/info_schema_table.h"
51
42
#include <algorithm>
54
#include <boost/unordered_set.hpp>
56
44
using namespace std;
61
extern pid_t current_pid;
63
bool is_primary_key(KeyInfo *key_info)
45
using namespace drizzled;
47
static const char hexchars[]= "0123456789abcdef";
48
bool is_primary_key(KEY *key_info)
65
50
static const char * primary_key_name="PRIMARY";
66
51
return (strcmp(key_info->name, primary_key_name)==0);
87
72
let's fetch the database default character set and
88
73
apply it to the table.
90
SchemaIdentifier identifier(db);
91
75
if (create_info->default_table_charset == NULL)
92
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
76
create_info->default_table_charset= get_default_db_collation(db);
80
Translate a cursor name to a table name (WL #1324).
83
filename_to_tablename()
86
to_length The size of the table name buffer.
91
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
95
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
97
/* Temporary table name. */
98
length= strlen(strncpy(to, from, to_length));
102
for (; *from && length < to_length; length++, from++)
109
/* We've found an escaped char - skip the @ */
112
/* There will be a two-position hex-char version of the char */
113
for (int x=1; x >= 0; x--)
115
if (*from >= '0' && *from <= '9')
116
to[length] += ((*from++ - '0') << (4 * x));
117
else if (*from >= 'a' && *from <= 'f')
118
to[length] += ((*from++ - 'a' + 10) << (4 * x));
120
/* Backup because we advanced extra in the inner loop */
130
Translate a table name to a cursor name (WL #1324).
133
tablename_to_filename()
135
to OUT The cursor name
136
to_length The size of the cursor name buffer.
139
true if errors happen. false on success.
141
bool tablename_to_filename(const char *from, char *to, size_t to_length)
145
for (; *from && length < to_length; length++, from++)
147
if ((*from >= '0' && *from <= '9') ||
148
(*from >= 'A' && *from <= 'Z') ||
149
(*from >= 'a' && *from <= 'z') ||
150
/* OSX defines an extra set of high-bit and multi-byte characters
151
that cannot be used on the filesystem. Instead of trying to sort
152
those out, we'll just escape encode all high-bit-set chars on OSX.
153
It won't really hurt anything - it'll just make some filenames ugly. */
154
#if !defined(TARGET_OS_OSX)
155
((unsigned char)*from >= 128) ||
165
if (length + 3 >= to_length)
168
/* We need to escape this char in a way that can be reversed */
170
to[length++]= hexchars[(*from >> 4) & 15];
171
to[length]= hexchars[(*from) & 15];
174
if (check_if_legal_tablename(to) &&
175
length + 4 < to_length)
177
memcpy(to + length, "@@@", 4);
185
Creates path to a cursor: drizzle_data_dir/db/table.ext
188
build_table_filename()
189
buff Where to write result
190
This may be the same as table_name.
193
table_name Table name
195
flags FN_FROM_IS_TMP or FN_TO_IS_TMP
196
table_name is temporary, do not change.
200
Uses database and table name, and extension to create
201
a cursor name in drizzle_data_dir. Database and table
202
names are converted from system_charset_info into "fscs".
203
Unless flags indicate a temporary table name.
204
'db' is always converted.
205
'ext' is not converted.
207
The conversion suppression is required for ALTER Table. This
208
statement creates intermediate tables. These are regular
209
(non-temporary) tables with a temporary name. Their path names must
210
be derivable from the table name. So we cannot use
211
build_tmptable_filename() for them.
214
path length on success, 0 on failure
217
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
219
char dbbuff[FN_REFLEN];
220
char tbbuff[FN_REFLEN];
221
bool conversion_error= false;
223
memset(tbbuff, 0, sizeof(tbbuff));
224
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
225
strncpy(tbbuff, table_name, sizeof(tbbuff));
228
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
229
if (conversion_error)
231
errmsg_printf(ERRMSG_LVL_ERROR,
232
_("Table name cannot be encoded and fit within filesystem "
233
"name length restrictions."));
237
memset(dbbuff, 0, sizeof(dbbuff));
238
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
239
if (conversion_error)
241
errmsg_printf(ERRMSG_LVL_ERROR,
242
_("Schema name cannot be encoded and fit within filesystem "
243
"name length restrictions."));
248
int rootdir_len= strlen(FN_ROOTDIR);
249
string table_path(drizzle_data_home);
250
int without_rootdir= table_path.length()-rootdir_len;
252
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
253
if (without_rootdir >= 0)
255
const char *tmp= table_path.c_str()+without_rootdir;
256
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
257
table_path.append(FN_ROOTDIR);
260
table_path.append(dbbuff);
261
table_path.append(FN_ROOTDIR);
262
table_path.append(tbbuff);
264
if (bufflen < table_path.length())
267
strcpy(buff, table_path.c_str());
269
return table_path.length();
274
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
277
build_tmptable_filename()
278
session The thread handle.
279
buff Where to write result
284
Uses current_pid, thread_id, and tmp_table counter to create
285
a cursor name in drizzle_tmpdir.
288
path length on success, 0 on failure
291
size_t build_tmptable_filename(char *buff, size_t bufflen)
294
ostringstream path_str, post_tmpdir_str;
297
Session *session= current_session;
299
path_str << drizzle_tmpdir;
300
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
301
post_tmpdir_str << session->thread_id << session->tmp_table++;
302
tmp= post_tmpdir_str.str();
304
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
308
if (bufflen < path_str.str().length())
311
length= unpack_filename(buff, path_str.str().c_str());
144
390
bool drop_temporary)
146
392
TableList *table;
393
char path[FN_REFLEN];
394
uint32_t path_length= 0;
147
395
String wrong_tables;
149
397
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
399
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
402
If we have the table in the definition cache, we don't have to check the
403
.frm cursor to find if the table is a normal table (not view) and what
407
for (table= tables; table; table= table->next_local)
410
table->db_type= NULL;
411
if ((share= TableShare::getShare(table->db, table->table_name)))
412
table->db_type= share->db_type();
415
if (!drop_temporary && lock_table_names_exclusively(session, tables))
417
pthread_mutex_unlock(&LOCK_open);
421
/* Don't give warnings for not found errors, as we already generate notes */
422
session->no_warnings_for_error= 1;
424
for (table= tables; table; table= table->next_local)
427
plugin::StorageEngine *table_type;
429
error= session->drop_temporary_table(table);
433
// removed temporary table
437
goto err_with_placeholders;
439
// temporary table not found
443
table_type= table->db_type;
444
if (drop_temporary == false)
447
abort_locked_tables(session, db, table->table_name);
448
remove_table_from_cache(session, db, table->table_name,
449
RTFC_WAIT_OTHER_THREAD_FLAG |
450
RTFC_CHECK_KILLED_FLAG);
452
If the table was used in lock tables, remember it so that
453
unlock_table_names can free it
455
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
456
table->table= locked_table;
461
goto err_with_placeholders;
463
/* remove .frm cursor and engine files */
464
path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
466
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
468
if (drop_temporary ||
470
&& (plugin::StorageEngine::getTableDefinition(*session,
471
identifier) != EEXIST))))
473
// Table was not found on disk and table can't be created from engine
475
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
476
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();
483
error= plugin::StorageEngine::dropTable(*session,
487
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
490
session->clear_error();
493
if (error == HA_ERR_ROW_IS_REFERENCED)
495
/* the table is referenced by a foreign key constraint */
496
foreign_key_error= true;
500
if (error == 0 || (if_exists && foreign_key_error == false))
501
write_bin_log_drop_table(session, if_exists, db, table->table_name);
505
if (wrong_tables.length())
506
wrong_tables.append(',');
507
wrong_tables.append(String(table->table_name,system_charset_info));
511
It's safe to unlock LOCK_open: we have an exclusive lock
514
pthread_mutex_unlock(&LOCK_open);
251
516
if (wrong_tables.length())
253
if (not foreign_key_error)
518
if (!foreign_key_error)
255
519
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
520
wrong_tables.c_ptr());
260
523
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
1518
Ignore the name of this function... it locks :(
1403
1547
bool mysql_create_table_no_lock(Session *session,
1404
const TableIdentifier &identifier,
1548
TableIdentifier &identifier,
1405
1549
HA_CREATE_INFO *create_info,
1406
message::Table &table_proto,
1550
message::Table *table_proto,
1407
1551
AlterInfo *alter_info,
1408
1552
bool internal_tmp_table,
1409
uint32_t select_field_count,
1553
uint32_t select_field_count,
1410
1554
bool is_if_not_exists)
1412
1556
uint db_options, key_count;
1413
KeyInfo *key_info_buffer;
1557
KEY *key_info_buffer;
1414
1559
bool error= true;
1561
bool lex_identified_temp_table=
1562
(table_proto->type() == drizzled::message::Table::TEMPORARY);
1416
1564
/* Check for duplicate fields and check type of table to create */
1417
if (not alter_info->create_list.elements)
1565
if (!alter_info->create_list.elements)
1419
1567
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1423
assert(identifier.getTableName() == table_proto.name());
1571
assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
1424
1572
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)
1573
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1574
db_options|=HA_OPTION_PACK_RECORD;
1575
if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1577
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1581
set_table_default_charset(create_info, identifier.getDBName());
1583
/* Check if table exists */
1584
if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1586
&db_options, cursor,
1587
&key_info_buffer, &key_count,
1588
select_field_count))
1591
/* Check if table already exists */
1592
if (lex_identified_temp_table &&
1593
session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1473
1595
if (is_if_not_exists)
1597
create_info->table_existed= 1; // Mark that table existed
1475
1598
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1476
1599
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);
1600
identifier.getTableName());
1604
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1608
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1609
if (!internal_tmp_table && ! lex_identified_temp_table)
1611
if (plugin::StorageEngine::getTableDefinition(*session,
1612
identifier)==EEXIST)
1614
if (is_if_not_exists)
1617
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1618
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1619
identifier.getTableName());
1620
create_info->table_existed= 1; // Mark that table existed
1623
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1625
goto unlock_and_end;
1628
We don't assert here, but check the result, because the table could be
1629
in the table definition cache and in the same time the .frm could be
1630
missing from the disk, in case of manual intervention which deletes
1631
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1632
Then she could create the table. This case is pretty obscure and
1633
therefore we don't introduce a new error message only for it.
1635
if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
1637
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1638
goto unlock_and_end;
1643
Check that table with given name does not already
1644
exist in any storage engine. In such a case it should
1645
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1646
unless user specified CREATE TABLE IF EXISTS
1647
The LOCK_open mutex has been locked to make sure no
1648
one else is attempting to discover the table. Since
1649
it's not on disk as a frm cursor, no one could be using it!
1651
if (! lex_identified_temp_table)
1653
int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
1658
/* Normal case, no table exists. we can go and create it */
1661
if (is_if_not_exists)
1664
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1665
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1666
identifier.getTableName());
1667
create_info->table_existed= 1; // Mark that table existed
1668
goto unlock_and_end;
1670
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1671
goto unlock_and_end;
1673
my_error(retcode, MYF(0), identifier.getTableName());
1674
goto unlock_and_end;
1678
session->set_proc_info("creating table");
1679
create_info->table_existed= 0; // Mark that table is created
1681
create_info->table_options=db_options;
1683
if (rea_create_table(session, identifier,
1685
create_info, alter_info->create_list,
1686
key_count, key_info_buffer))
1687
goto unlock_and_end;
1689
if (lex_identified_temp_table)
1691
/* Open table and put in temporary table list */
1692
if (!(session->open_temporary_table(identifier)))
1694
(void) session->rm_temporary_table(create_info->db_type, identifier);
1695
goto unlock_and_end;
1700
Don't write statement if:
1701
- It is an internal temporary table,
1702
- Row-based logging is used and it we are creating a temporary table, or
1703
- The binary log is not open.
1704
Otherwise, the statement shall be binlogged.
1706
if (!internal_tmp_table && ! lex_identified_temp_table)
1707
write_bin_log(session, session->query, session->query_length);
1710
pthread_mutex_unlock(&LOCK_open);
1713
session->set_proc_info("After create");
1512
1720
Database locking aware wrapper for mysql_create_table_no_lock(),
1514
1723
bool mysql_create_table(Session *session,
1515
const TableIdentifier &identifier,
1724
TableIdentifier &identifier,
1516
1725
HA_CREATE_INFO *create_info,
1517
message::Table &table_proto,
1726
message::Table *table_proto,
1518
1727
AlterInfo *alter_info,
1519
1728
bool internal_tmp_table,
1520
1729
uint32_t select_field_count,
1521
1730
bool is_if_not_exists)
1523
if (identifier.isTmp())
1525
return mysql_create_table_no_lock(session,
1535
return drizzle_create_table(session,
1732
Table *name_lock= NULL;
1734
bool lex_identified_temp_table=
1735
(table_proto->type() == drizzled::message::Table::TEMPORARY);
1737
if (! lex_identified_temp_table)
1739
if (session->lock_table_name_if_not_cached(identifier.getDBName(),
1740
identifier.getTableName(),
1746
if (name_lock == NULL)
1748
if (is_if_not_exists)
1750
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1751
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1752
identifier.getTableName());
1753
create_info->table_existed= 1;
1758
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1765
result= mysql_create_table_no_lock(session,
1777
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1778
session->unlink_open_table(name_lock);
1779
pthread_mutex_unlock(&LOCK_open);
1609
mysql_rename_table(Session &session,
1610
plugin::StorageEngine *base,
1611
const TableIdentifier &from,
1612
const TableIdentifier &to)
1851
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
1852
const char *old_name, const char *new_db,
1853
const char *new_name, uint32_t flags)
1855
Session *session= current_session;
1856
char from[FN_REFLEN], to[FN_REFLEN];
1857
char *from_base= from, *to_base= to;
1618
if (not plugin::StorageEngine::doesSchemaExist(to))
1862
build_table_filename(from, sizeof(from), old_db, old_name,
1863
flags & FN_FROM_IS_TMP);
1864
build_table_filename(to, sizeof(to), new_db, new_name,
1865
flags & FN_TO_IS_TMP);
1867
if (!(error= base->renameTable(session, from_base, to_base)))
1620
my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1869
if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
1870
&& rename_table_proto_file(from_base, to_base))
1873
base->renameTable(session, to_base, from_base);
1624
error= base->renameTable(session, from, to);
1626
1877
if (error == HA_ERR_WRONG_COMMAND)
1628
1878
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1630
1879
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;
1880
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
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,
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;
2034
2226
Create a table identical to the specified table
2067
2266
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());
2269
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2272
TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ?
2273
(engine_arg->check_flag(HTON_BIT_DOES_TRANSACTIONS) ? TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE) :
2076
2277
Check that destination tables does not exist. Note that its name
2077
2278
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());
2280
if (lex_identified_temp_table)
2282
if (session->find_temporary_table(db, table_name))
2287
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2292
if (plugin::StorageEngine::getTableDefinition(*session,
2293
destination_identifier) == EEXIST)
2298
Create a new table by copying from source table
2300
Altough exclusive name-lock on target table protects us from concurrent
2301
DML and DDL operations on it we still want to wrap .FRM creation and call
2302
to plugin::StorageEngine::createTable() in critical section protected by
2303
LOCK_open in order to provide minimal atomicity against operations which
2304
disregard name-locks, like I_S implementation, for example. This is a
2305
temporary and should not be copied. Instead we should fix our code to
2306
always honor name-locks.
2308
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2309
during the call to plugin::StorageEngine::createTable().
2310
See bug #28614 for more info.
2312
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2314
int protoerr= EEXIST;
2317
* If an engine was not specified and we are reading from an I_S table, then we need to toss an
2318
* error. This should go away soon.
2319
* @todo make this go away!
2321
if (! is_engine_set)
2323
string tab_name(src_path);
2324
string i_s_prefix("./information_schema/");
2325
if (tab_name.compare(0, i_s_prefix.length(), i_s_prefix) == 0)
2327
pthread_mutex_unlock(&LOCK_open);
2328
my_error(ER_ILLEGAL_HA_CREATE_OPTION,
2330
"INFORMATION_ENGINE",
2336
protoerr= plugin::StorageEngine::getTableDefinition(*session,
2343
message::Table new_proto(src_proto);
2345
if (lex_identified_temp_table)
2347
new_proto.set_type(message::Table::TEMPORARY);
2351
new_proto.set_type(message::Table::STANDARD);
2356
message::Table::StorageEngine *protoengine;
2358
protoengine= new_proto.mutable_engine();
2359
protoengine->set_name(create_table_proto.engine().name());
2362
if (protoerr == EEXIST)
2364
plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
2365
new_proto.engine().name());
2367
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2369
string dst_proto_path(destination_identifier.getPath());
2370
dst_proto_path.append(".dfe");
2372
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
2382
if (my_errno == ENOENT)
2383
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2385
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), my_errno);
2386
pthread_mutex_unlock(&LOCK_open);
2391
As mysql_truncate don't work on a new table at this stage of
2392
creation, instead create the table directly (for both normal
2393
and temporary tables).
2395
err= plugin::StorageEngine::createTable(*session,
2396
destination_identifier,
2399
pthread_mutex_unlock(&LOCK_open);
2401
if (lex_identified_temp_table)
2403
if (err || !session->open_temporary_table(destination_identifier))
2405
(void) session->rm_temporary_table(engine_arg, destination_identifier);
2411
(void) quick_rm_table(*session, db,
2417
We have to write the query before we unlock the tables.
2421
Since temporary tables are not replicated under row-based
2422
replication, CREATE TABLE ... LIKE ... needs special
2423
treatement. We have four cases to consider, according to the
2424
following decision table:
2426
==== ========= ========= ==============================
2427
Case Target Source Write to binary log
2428
==== ========= ========= ==============================
2429
1 normal normal Original statement
2430
2 normal temporary Generated statement
2431
3 temporary normal Nothing
2432
4 temporary temporary Nothing
2433
==== ========= ========= ==============================
2435
if (! lex_identified_temp_table)
2437
if (src_table->table->s->tmp_table) // Case 2
2440
String query(buf, sizeof(buf), system_charset_info);
2441
query.length(0); // Have to zero it since constructor doesn't
2445
Here we open the destination table, on which we already have
2446
name-lock. This is needed for store_create_info() to work.
2447
The table will be closed by unlink_open_table() at the end
2450
table->table= name_lock;
2451
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2452
if (session->reopen_name_locked_table(table, false))
2454
pthread_mutex_unlock(&LOCK_open);
2457
pthread_mutex_unlock(&LOCK_open);
2459
int result= store_create_info(table, &query, is_if_not_exists);
2461
assert(result == 0); // store_create_info() always return 0
2462
write_bin_log(session, query.ptr(), query.length());
2465
write_bin_log(session, session->query, session->query_length);
2473
if (is_if_not_exists)
2475
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2476
snprintf(warn_buff, sizeof(warn_buff),
2477
ER(ER_TABLE_EXISTS_ERROR), table_name);
2478
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2479
ER_TABLE_EXISTS_ERROR,warn_buff);
2483
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2488
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2489
session->unlink_open_table(name_lock);
2490
pthread_mutex_unlock(&LOCK_open);
2193
2510
return(mysql_admin_table(session, tables, check_opt,
2194
2511
"check", lock_type,
2512
0, 0, HA_OPEN_FOR_REPAIR, 0,
2196
2513
&Cursor::ha_check));
2199
} /* namespace drizzled */
2517
Recreates tables by calling drizzled::alter_table().
2520
mysql_recreate_table()
2521
session Thread Cursor
2522
tables Tables to recreate
2525
Like drizzled::alter_table().
2527
bool mysql_recreate_table(Session *session, TableList *table_list)
2529
HA_CREATE_INFO create_info;
2530
AlterInfo alter_info;
2531
message::Table table_proto;
2533
assert(!table_list->next_global);
2535
table_list->table has been closed and freed. Do not reference
2536
uninitialized data. open_tables() could fail.
2538
table_list->table= NULL;
2540
memset(&create_info, 0, sizeof(create_info));
2541
create_info.row_type=ROW_TYPE_NOT_USED;
2542
create_info.default_table_charset=default_charset_info;
2543
/* Force alter table to recreate table */
2544
alter_info.flags.set(ALTER_CHANGE_COLUMN);
2545
alter_info.flags.set(ALTER_RECREATE);
2546
return(alter_table(session, NULL, NULL, &create_info, &table_proto,
2547
table_list, &alter_info, 0,
2548
(order_st *) 0, 0));
2552
bool mysql_checksum_table(Session *session, TableList *tables,
2556
List<Item> field_list;
2559
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2560
item->maybe_null= 1;
2561
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2562
MY_INT64_NUM_DECIMAL_DIGITS));
2563
item->maybe_null= 1;
2564
if (session->client->sendFields(&field_list))
2567
/* Open one table after the other to keep lock time as short as possible. */
2568
for (table= tables; table; table= table->next_local)
2570
char table_name[NAME_LEN*2+2];
2573
sprintf(table_name,"%s.%s",table->db,table->table_name);
2575
t= table->table= session->openTableLock(table, TL_READ);
2576
session->clear_error(); // these errors shouldn't get client
2578
session->client->store(table_name);
2582
/* Table didn't exist */
2583
session->client->store();
2584
session->clear_error();
2589
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2591
if (t->cursor->ha_table_flags() & HA_HAS_CHECKSUM)
2592
session->client->store((uint64_t)t->cursor->checksum());
2595
/* calculating table's checksum */
2597
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2599
t->use_all_columns();
2601
if (t->cursor->ha_rnd_init(1))
2602
session->client->store();
2607
ha_checksum row_crc= 0;
2608
int error= t->cursor->rnd_next(t->record[0]);
2609
if (unlikely(error))
2611
if (error == HA_ERR_RECORD_DELETED)
2615
if (t->s->null_bytes)
2617
/* fix undefined null bits */
2618
t->record[0][t->s->null_bytes-1] |= null_mask;
2619
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2620
t->record[0][0] |= 1;
2622
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2625
for (uint32_t i= 0; i < t->s->fields; i++ )
2627
Field *f= t->field[i];
2628
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2629
(f->type() == DRIZZLE_TYPE_VARCHAR))
2633
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2636
row_crc= my_checksum(row_crc, f->ptr,
2642
session->client->store((uint64_t)crc);
2643
t->cursor->ha_rnd_end();
2646
session->clear_error();
2647
session->close_thread_tables();
2648
table->table=0; // For query cache
2650
if (session->client->flush())
2658
session->close_thread_tables(); // Shouldn't be needed