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"
37
#include <drizzled/table_identifier.h>
39
#include "drizzled/statement/alter_table.h" /* for drizzled::create_like_schema_frm, which will die soon */
51
41
#include <algorithm>
54
#include <boost/unordered_set.hpp>
56
43
using namespace std;
61
extern pid_t current_pid;
63
bool is_primary_key(KeyInfo *key_info)
44
using namespace drizzled;
46
static const char hexchars[]= "0123456789abcdef";
47
bool is_primary_key(KEY *key_info)
65
49
static const char * primary_key_name="PRIMARY";
66
50
return (strcmp(key_info->name, primary_key_name)==0);
87
71
let's fetch the database default character set and
88
72
apply it to the table.
90
SchemaIdentifier identifier(db);
91
74
if (create_info->default_table_charset == NULL)
92
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
75
create_info->default_table_charset= get_default_db_collation(db);
79
Translate a cursor name to a table name (WL #1324).
82
filename_to_tablename()
85
to_length The size of the table name buffer.
90
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
94
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
96
/* Temporary table name. */
97
length= strlen(strncpy(to, from, to_length));
101
for (; *from && length < to_length; length++, from++)
108
/* We've found an escaped char - skip the @ */
111
/* There will be a two-position hex-char version of the char */
112
for (int x=1; x >= 0; x--)
114
if (*from >= '0' && *from <= '9')
115
to[length] += ((*from++ - '0') << (4 * x));
116
else if (*from >= 'a' && *from <= 'f')
117
to[length] += ((*from++ - 'a' + 10) << (4 * x));
119
/* Backup because we advanced extra in the inner loop */
129
Translate a table name to a cursor name (WL #1324).
132
tablename_to_filename()
134
to OUT The cursor name
135
to_length The size of the cursor name buffer.
138
true if errors happen. false on success.
140
bool tablename_to_filename(const char *from, char *to, size_t to_length)
144
for (; *from && length < to_length; length++, from++)
146
if ((*from >= '0' && *from <= '9') ||
147
(*from >= 'A' && *from <= 'Z') ||
148
(*from >= 'a' && *from <= 'z') ||
149
/* OSX defines an extra set of high-bit and multi-byte characters
150
that cannot be used on the filesystem. Instead of trying to sort
151
those out, we'll just escape encode all high-bit-set chars on OSX.
152
It won't really hurt anything - it'll just make some filenames ugly. */
153
#if !defined(TARGET_OS_OSX)
154
((unsigned char)*from >= 128) ||
164
if (length + 3 >= to_length)
167
/* We need to escape this char in a way that can be reversed */
169
to[length++]= hexchars[(*from >> 4) & 15];
170
to[length]= hexchars[(*from) & 15];
173
if (check_if_legal_tablename(to) &&
174
length + 4 < to_length)
176
memcpy(to + length, "@@@", 4);
184
Creates path to a cursor: drizzle_data_dir/db/table.ext
187
build_table_filename()
188
buff Where to write result
189
This may be the same as table_name.
192
table_name Table name
194
flags FN_FROM_IS_TMP or FN_TO_IS_TMP
195
table_name is temporary, do not change.
199
Uses database and table name, and extension to create
200
a cursor name in drizzle_data_dir. Database and table
201
names are converted from system_charset_info into "fscs".
202
Unless flags indicate a temporary table name.
203
'db' is always converted.
204
'ext' is not converted.
206
The conversion suppression is required for ALTER Table. This
207
statement creates intermediate tables. These are regular
208
(non-temporary) tables with a temporary name. Their path names must
209
be derivable from the table name. So we cannot use
210
build_tmptable_filename() for them.
213
path length on success, 0 on failure
216
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
218
char dbbuff[FN_REFLEN];
219
char tbbuff[FN_REFLEN];
220
bool conversion_error= false;
222
memset(tbbuff, 0, sizeof(tbbuff));
223
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
224
strncpy(tbbuff, table_name, sizeof(tbbuff));
227
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
228
if (conversion_error)
230
errmsg_printf(ERRMSG_LVL_ERROR,
231
_("Table name cannot be encoded and fit within filesystem "
232
"name length restrictions."));
236
memset(dbbuff, 0, sizeof(dbbuff));
237
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
238
if (conversion_error)
240
errmsg_printf(ERRMSG_LVL_ERROR,
241
_("Schema name cannot be encoded and fit within filesystem "
242
"name length restrictions."));
247
int rootdir_len= strlen(FN_ROOTDIR);
248
string table_path(drizzle_data_home);
249
int without_rootdir= table_path.length()-rootdir_len;
251
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
252
if (without_rootdir >= 0)
254
const char *tmp= table_path.c_str()+without_rootdir;
255
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
256
table_path.append(FN_ROOTDIR);
259
table_path.append(dbbuff);
260
table_path.append(FN_ROOTDIR);
261
table_path.append(tbbuff);
263
if (bufflen < table_path.length())
266
strcpy(buff, table_path.c_str());
268
return table_path.length();
273
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
276
build_tmptable_filename()
277
session The thread handle.
278
buff Where to write result
283
Uses current_pid, thread_id, and tmp_table counter to create
284
a cursor name in drizzle_tmpdir.
287
path length on success, 0 on failure
290
size_t build_tmptable_filename(char *buff, size_t bufflen)
293
ostringstream path_str, post_tmpdir_str;
296
Session *session= current_session;
298
path_str << drizzle_tmpdir;
299
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
300
post_tmpdir_str << session->thread_id << session->tmp_table++;
301
tmp= post_tmpdir_str.str();
303
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
307
if (bufflen < path_str.str().length())
310
length= unpack_filename(buff, path_str.str().c_str());
144
389
bool drop_temporary)
146
391
TableList *table;
392
char path[FN_REFLEN];
393
uint32_t path_length= 0;
147
394
String wrong_tables;
149
396
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
398
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
401
If we have the table in the definition cache, we don't have to check the
402
.frm cursor to find if the table is a normal table (not view) and what
406
for (table= tables; table; table= table->next_local)
409
table->db_type= NULL;
410
if ((share= TableShare::getShare(table->db, table->table_name)))
411
table->db_type= share->db_type();
414
if (!drop_temporary && lock_table_names_exclusively(session, tables))
416
pthread_mutex_unlock(&LOCK_open);
420
/* Don't give warnings for not found errors, as we already generate notes */
421
session->no_warnings_for_error= 1;
423
for (table= tables; table; table= table->next_local)
426
plugin::StorageEngine *table_type;
428
error= session->drop_temporary_table(table);
432
// removed temporary table
436
goto err_with_placeholders;
438
// temporary table not found
442
table_type= table->db_type;
443
if (drop_temporary == false)
446
abort_locked_tables(session, db, table->table_name);
447
remove_table_from_cache(session, db, table->table_name,
448
RTFC_WAIT_OTHER_THREAD_FLAG |
449
RTFC_CHECK_KILLED_FLAG);
451
If the table was used in lock tables, remember it so that
452
unlock_table_names can free it
454
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
455
table->table= locked_table;
460
goto err_with_placeholders;
462
/* remove .frm cursor and engine files */
463
path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
465
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
467
if (drop_temporary ||
469
&& (plugin::StorageEngine::getTableDefinition(*session,
470
identifier) != EEXIST))))
472
// Table was not found on disk and table can't be created from engine
474
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
475
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();
482
error= plugin::StorageEngine::dropTable(*session,
486
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
489
session->clear_error();
492
if (error == HA_ERR_ROW_IS_REFERENCED)
494
/* the table is referenced by a foreign key constraint */
495
foreign_key_error= true;
499
if (error == 0 || (if_exists && foreign_key_error == false))
500
write_bin_log_drop_table(session, if_exists, db, table->table_name);
504
if (wrong_tables.length())
505
wrong_tables.append(',');
506
wrong_tables.append(String(table->table_name,system_charset_info));
510
It's safe to unlock LOCK_open: we have an exclusive lock
513
pthread_mutex_unlock(&LOCK_open);
251
515
if (wrong_tables.length())
253
if (not foreign_key_error)
517
if (!foreign_key_error)
255
518
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
519
wrong_tables.c_ptr());
260
522
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
1517
Ignore the name of this function... it locks :(
1403
1546
bool mysql_create_table_no_lock(Session *session,
1404
const TableIdentifier &identifier,
1547
TableIdentifier &identifier,
1405
1548
HA_CREATE_INFO *create_info,
1406
message::Table &table_proto,
1549
message::Table *table_proto,
1407
1550
AlterInfo *alter_info,
1408
1551
bool internal_tmp_table,
1409
uint32_t select_field_count,
1552
uint32_t select_field_count,
1410
1553
bool is_if_not_exists)
1412
1555
uint db_options, key_count;
1413
KeyInfo *key_info_buffer;
1556
KEY *key_info_buffer;
1414
1558
bool error= true;
1560
bool lex_identified_temp_table=
1561
(table_proto->type() == drizzled::message::Table::TEMPORARY);
1416
1563
/* Check for duplicate fields and check type of table to create */
1417
if (not alter_info->create_list.elements)
1564
if (!alter_info->create_list.elements)
1419
1566
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1423
assert(identifier.getTableName() == table_proto.name());
1570
assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
1424
1571
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)
1572
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1573
db_options|=HA_OPTION_PACK_RECORD;
1574
if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1576
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1580
set_table_default_charset(create_info, identifier.getDBName());
1582
/* Check if table exists */
1583
if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1585
&db_options, cursor,
1586
&key_info_buffer, &key_count,
1587
select_field_count))
1590
/* Check if table already exists */
1591
if (lex_identified_temp_table &&
1592
session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1473
1594
if (is_if_not_exists)
1596
create_info->table_existed= 1; // Mark that table existed
1475
1597
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1476
1598
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);
1599
identifier.getTableName());
1603
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1607
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1608
if (!internal_tmp_table && ! lex_identified_temp_table)
1610
if (plugin::StorageEngine::getTableDefinition(*session,
1611
identifier)==EEXIST)
1613
if (is_if_not_exists)
1616
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1617
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1618
identifier.getTableName());
1619
create_info->table_existed= 1; // Mark that table existed
1622
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1624
goto unlock_and_end;
1627
We don't assert here, but check the result, because the table could be
1628
in the table definition cache and in the same time the .frm could be
1629
missing from the disk, in case of manual intervention which deletes
1630
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1631
Then she could create the table. This case is pretty obscure and
1632
therefore we don't introduce a new error message only for it.
1634
if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
1636
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1637
goto unlock_and_end;
1642
Check that table with given name does not already
1643
exist in any storage engine. In such a case it should
1644
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1645
unless user specified CREATE TABLE IF EXISTS
1646
The LOCK_open mutex has been locked to make sure no
1647
one else is attempting to discover the table. Since
1648
it's not on disk as a frm cursor, no one could be using it!
1650
if (! lex_identified_temp_table)
1652
int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
1657
/* Normal case, no table exists. we can go and create it */
1660
if (is_if_not_exists)
1663
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1664
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1665
identifier.getTableName());
1666
create_info->table_existed= 1; // Mark that table existed
1667
goto unlock_and_end;
1669
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1670
goto unlock_and_end;
1672
my_error(retcode, MYF(0), identifier.getTableName());
1673
goto unlock_and_end;
1677
session->set_proc_info("creating table");
1678
create_info->table_existed= 0; // Mark that table is created
1680
create_info->table_options=db_options;
1682
if (rea_create_table(session, identifier,
1684
create_info, alter_info->create_list,
1685
key_count, key_info_buffer))
1686
goto unlock_and_end;
1688
if (lex_identified_temp_table)
1690
/* Open table and put in temporary table list */
1691
if (!(session->open_temporary_table(identifier)))
1693
(void) session->rm_temporary_table(create_info->db_type, identifier);
1694
goto unlock_and_end;
1699
Don't write statement if:
1700
- It is an internal temporary table,
1701
- Row-based logging is used and it we are creating a temporary table, or
1702
- The binary log is not open.
1703
Otherwise, the statement shall be binlogged.
1705
if (!internal_tmp_table && ! lex_identified_temp_table)
1706
write_bin_log(session, session->query, session->query_length);
1709
pthread_mutex_unlock(&LOCK_open);
1712
session->set_proc_info("After create");
1512
1719
Database locking aware wrapper for mysql_create_table_no_lock(),
1514
1722
bool mysql_create_table(Session *session,
1515
const TableIdentifier &identifier,
1723
TableIdentifier &identifier,
1516
1724
HA_CREATE_INFO *create_info,
1517
message::Table &table_proto,
1725
message::Table *table_proto,
1518
1726
AlterInfo *alter_info,
1519
1727
bool internal_tmp_table,
1520
1728
uint32_t select_field_count,
1521
1729
bool is_if_not_exists)
1523
if (identifier.isTmp())
1525
return mysql_create_table_no_lock(session,
1535
return drizzle_create_table(session,
1731
Table *name_lock= NULL;
1733
bool lex_identified_temp_table=
1734
(table_proto->type() == drizzled::message::Table::TEMPORARY);
1736
if (! lex_identified_temp_table)
1738
if (session->lock_table_name_if_not_cached(identifier.getDBName(),
1739
identifier.getTableName(),
1745
if (name_lock == NULL)
1747
if (is_if_not_exists)
1749
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1750
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1751
identifier.getTableName());
1752
create_info->table_existed= 1;
1757
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1764
result= mysql_create_table_no_lock(session,
1776
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1777
session->unlink_open_table(name_lock);
1778
pthread_mutex_unlock(&LOCK_open);
1609
mysql_rename_table(Session &session,
1610
plugin::StorageEngine *base,
1611
const TableIdentifier &from,
1612
const TableIdentifier &to)
1850
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
1851
const char *old_name, const char *new_db,
1852
const char *new_name, uint32_t flags)
1854
Session *session= current_session;
1855
char from[FN_REFLEN], to[FN_REFLEN];
1856
char *from_base= from, *to_base= to;
1618
if (not plugin::StorageEngine::doesSchemaExist(to))
1861
build_table_filename(from, sizeof(from), old_db, old_name,
1862
flags & FN_FROM_IS_TMP);
1863
build_table_filename(to, sizeof(to), new_db, new_name,
1864
flags & FN_TO_IS_TMP);
1866
if (!(error= base->renameTable(session, from_base, to_base)))
1620
my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1868
if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
1869
&& rename_table_proto_file(from_base, to_base))
1872
base->renameTable(session, to_base, from_base);
1624
error= base->renameTable(session, from, to);
1626
1876
if (error == HA_ERR_WRONG_COMMAND)
1628
1877
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1630
1878
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;
1879
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
2225
Create a table identical to the specified table
2067
2265
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());
2268
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2271
TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ?
2272
(engine_arg->check_flag(HTON_BIT_DOES_TRANSACTIONS) ? TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE) :
2076
2276
Check that destination tables does not exist. Note that its name
2077
2277
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());
2279
if (lex_identified_temp_table)
2281
if (session->find_temporary_table(db, table_name))
2286
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2291
if (plugin::StorageEngine::getTableDefinition(*session,
2292
destination_identifier) == EEXIST)
2297
Create a new table by copying from source table
2299
Altough exclusive name-lock on target table protects us from concurrent
2300
DML and DDL operations on it we still want to wrap .FRM creation and call
2301
to plugin::StorageEngine::createTable() in critical section protected by
2302
LOCK_open in order to provide minimal atomicity against operations which
2303
disregard name-locks, like I_S implementation, for example. This is a
2304
temporary and should not be copied. Instead we should fix our code to
2305
always honor name-locks.
2307
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2308
during the call to plugin::StorageEngine::createTable().
2309
See bug #28614 for more info.
2311
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2313
int protoerr= EEXIST;
2315
if (src_table->schema_table)
2318
If engine was not specified and we are reading from the I_S, then we need to
2319
toss an error. This should go away later on when we straighten out the
2322
if (! is_engine_set)
2324
pthread_mutex_unlock(&LOCK_open);
2325
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2326
"INFORMATION_ENGINE",
2331
if (create_like_schema_frm(session, src_table, &src_proto))
2333
pthread_mutex_unlock(&LOCK_open);
2339
protoerr= plugin::StorageEngine::getTableDefinition(*session,
2347
message::Table new_proto(src_proto);
2349
if (lex_identified_temp_table)
2351
new_proto.set_type(message::Table::TEMPORARY);
2355
new_proto.set_type(message::Table::STANDARD);
2360
message::Table::StorageEngine *protoengine;
2362
protoengine= new_proto.mutable_engine();
2363
protoengine->set_name(create_table_proto.engine().name());
2366
if (protoerr == EEXIST)
2368
plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
2369
new_proto.engine().name());
2371
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2373
string dst_proto_path(destination_identifier.getPath());
2374
dst_proto_path.append(".dfe");
2376
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
2386
if (my_errno == ENOENT)
2387
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2389
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), my_errno);
2390
pthread_mutex_unlock(&LOCK_open);
2395
As mysql_truncate don't work on a new table at this stage of
2396
creation, instead create the table directly (for both normal
2397
and temporary tables).
2399
err= plugin::StorageEngine::createTable(*session,
2400
destination_identifier,
2403
pthread_mutex_unlock(&LOCK_open);
2405
if (lex_identified_temp_table)
2407
if (err || !session->open_temporary_table(destination_identifier))
2409
(void) session->rm_temporary_table(engine_arg, destination_identifier);
2415
(void) quick_rm_table(*session, db,
2421
We have to write the query before we unlock the tables.
2425
Since temporary tables are not replicated under row-based
2426
replication, CREATE TABLE ... LIKE ... needs special
2427
treatement. We have four cases to consider, according to the
2428
following decision table:
2430
==== ========= ========= ==============================
2431
Case Target Source Write to binary log
2432
==== ========= ========= ==============================
2433
1 normal normal Original statement
2434
2 normal temporary Generated statement
2435
3 temporary normal Nothing
2436
4 temporary temporary Nothing
2437
==== ========= ========= ==============================
2439
if (! lex_identified_temp_table)
2441
if (src_table->table->s->tmp_table) // Case 2
2444
String query(buf, sizeof(buf), system_charset_info);
2445
query.length(0); // Have to zero it since constructor doesn't
2449
Here we open the destination table, on which we already have
2450
name-lock. This is needed for store_create_info() to work.
2451
The table will be closed by unlink_open_table() at the end
2454
table->table= name_lock;
2455
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2456
if (session->reopen_name_locked_table(table, false))
2458
pthread_mutex_unlock(&LOCK_open);
2461
pthread_mutex_unlock(&LOCK_open);
2463
int result= store_create_info(table, &query, is_if_not_exists);
2465
assert(result == 0); // store_create_info() always return 0
2466
write_bin_log(session, query.ptr(), query.length());
2469
write_bin_log(session, session->query, session->query_length);
2477
if (is_if_not_exists)
2479
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2480
snprintf(warn_buff, sizeof(warn_buff),
2481
ER(ER_TABLE_EXISTS_ERROR), table_name);
2482
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2483
ER_TABLE_EXISTS_ERROR,warn_buff);
2487
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2492
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2493
session->unlink_open_table(name_lock);
2494
pthread_mutex_unlock(&LOCK_open);
2193
2514
return(mysql_admin_table(session, tables, check_opt,
2194
2515
"check", lock_type,
2516
0, 0, HA_OPEN_FOR_REPAIR, 0,
2196
2517
&Cursor::ha_check));
2199
} /* namespace drizzled */
2521
Recreates tables by calling drizzled::alter_table().
2524
mysql_recreate_table()
2525
session Thread Cursor
2526
tables Tables to recreate
2529
Like drizzled::alter_table().
2531
bool mysql_recreate_table(Session *session, TableList *table_list)
2533
HA_CREATE_INFO create_info;
2534
AlterInfo alter_info;
2535
message::Table table_proto;
2537
assert(!table_list->next_global);
2539
table_list->table has been closed and freed. Do not reference
2540
uninitialized data. open_tables() could fail.
2542
table_list->table= NULL;
2544
memset(&create_info, 0, sizeof(create_info));
2545
create_info.row_type=ROW_TYPE_NOT_USED;
2546
create_info.default_table_charset=default_charset_info;
2547
/* Force alter table to recreate table */
2548
alter_info.flags.set(ALTER_CHANGE_COLUMN);
2549
alter_info.flags.set(ALTER_RECREATE);
2550
return(alter_table(session, NULL, NULL, &create_info, &table_proto,
2551
table_list, &alter_info, 0,
2552
(order_st *) 0, 0));
2556
bool mysql_checksum_table(Session *session, TableList *tables,
2560
List<Item> field_list;
2563
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2564
item->maybe_null= 1;
2565
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2566
MY_INT64_NUM_DECIMAL_DIGITS));
2567
item->maybe_null= 1;
2568
if (session->client->sendFields(&field_list))
2571
/* Open one table after the other to keep lock time as short as possible. */
2572
for (table= tables; table; table= table->next_local)
2574
char table_name[NAME_LEN*2+2];
2577
sprintf(table_name,"%s.%s",table->db,table->table_name);
2579
t= table->table= session->openTableLock(table, TL_READ);
2580
session->clear_error(); // these errors shouldn't get client
2582
session->client->store(table_name);
2586
/* Table didn't exist */
2587
session->client->store();
2588
session->clear_error();
2593
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2595
if (t->cursor->ha_table_flags() & HA_HAS_CHECKSUM)
2596
session->client->store((uint64_t)t->cursor->checksum());
2599
/* calculating table's checksum */
2601
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2603
t->use_all_columns();
2605
if (t->cursor->ha_rnd_init(1))
2606
session->client->store();
2611
ha_checksum row_crc= 0;
2612
int error= t->cursor->rnd_next(t->record[0]);
2613
if (unlikely(error))
2615
if (error == HA_ERR_RECORD_DELETED)
2619
if (t->s->null_bytes)
2621
/* fix undefined null bits */
2622
t->record[0][t->s->null_bytes-1] |= null_mask;
2623
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2624
t->record[0][0] |= 1;
2626
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2629
for (uint32_t i= 0; i < t->s->fields; i++ )
2631
Field *f= t->field[i];
2632
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2633
(f->type() == DRIZZLE_TYPE_VARCHAR))
2637
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2640
row_crc= my_checksum(row_crc, f->ptr,
2646
session->client->store((uint64_t)crc);
2647
t->cursor->ha_rnd_end();
2650
session->clear_error();
2651
session->close_thread_tables();
2652
table->table=0; // For query cache
2654
if (session->client->flush())
2662
session->close_thread_tables(); // Shouldn't be needed