32
32
#include <drizzled/unireg.h>
33
33
#include <drizzled/item/int.h>
34
34
#include <drizzled/item/empty_string.h>
35
#include <drizzled/transaction_services.h>
35
#include <drizzled/replication_services.h>
36
36
#include "drizzled/transaction_services.h"
37
37
#include <drizzled/table_proto.h>
38
38
#include <drizzled/plugin/client.h>
39
#include <drizzled/identifier.h>
39
#include <drizzled/table_identifier.h>
40
40
#include "drizzled/internal/m_string.h"
41
41
#include "drizzled/global_charset_info.h"
42
42
#include "drizzled/charset.h"
44
#include "drizzled/definition/cache.h"
47
45
#include "drizzled/statement/alter_table.h"
48
46
#include "drizzled/sql_table.h"
49
47
#include "drizzled/pthread_globals.h"
50
#include "drizzled/plugin/storage_engine.h"
52
49
#include <algorithm>
55
#include <boost/unordered_set.hpp>
57
52
using namespace std;
62
bool is_primary_key(KeyInfo *key_info)
57
extern plugin::StorageEngine *myisam_engine;
58
extern pid_t current_pid;
60
bool is_primary_key(KEY *key_info)
64
62
static const char * primary_key_name="PRIMARY";
65
63
return (strcmp(key_info->name, primary_key_name)==0);
109
void write_bin_log(Session *session, const std::string &query)
111
TransactionServices &transaction_services= TransactionServices::singleton();
112
transaction_services.rawStatement(*session, query);
106
void write_bin_log(Session *session,
109
ReplicationServices &replication_services= ReplicationServices::singleton();
110
replication_services.rawStatement(session, query);
114
/* Should should be refactored to go away */
115
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
117
ReplicationServices &replication_services= ReplicationServices::singleton();
121
built_query.append("DROP TABLE IF EXISTS ");
123
built_query.append("DROP TABLE ");
125
built_query.append("`");
126
if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
128
built_query.append(db_name);
129
built_query.append("`.`");
132
built_query.append(table_name);
133
built_query.append("`");
134
replication_services.rawStatement(session, built_query);
116
138
Execute the drop of a normal or temporary table
141
mysql_rm_table_part2()
120
142
session Thread Cursor
121
143
tables Tables to drop
122
144
if_exists If set, don't give an error if table doesn't exists.
123
145
In this case we give an warning of level 'NOTE'
124
146
drop_temporary Only drop temporary tables
127
149
When logging to the binary log, we should log
128
150
tmp_tables and transactional tables as separate statements if we
129
151
are in a transaction; This is needed to get these tables into the
139
161
-1 Thread was killed
142
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
164
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
145
167
TableList *table;
146
168
String wrong_tables;
148
170
bool foreign_key_error= false;
152
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
154
if (not drop_temporary && session->lock_table_names_exclusively(tables))
159
/* Don't give warnings for not found errors, as we already generate notes */
160
session->no_warnings_for_error= 1;
162
for (table= tables; table; table= table->next_local)
164
identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
166
error= session->drop_temporary_table(tmp_identifier);
170
// removed temporary table
172
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
175
If we have the table in the definition cache, we don't have to check the
176
.frm cursor to find if the table is a normal table (not view) and what
180
for (table= tables; table; table= table->next_local)
183
table->db_type= NULL;
184
if ((share= TableShare::getShare(table->db, table->table_name)))
185
table->db_type= share->db_type();
188
if (not drop_temporary && lock_table_names_exclusively(session, tables))
190
pthread_mutex_unlock(&LOCK_open);
194
/* Don't give warnings for not found errors, as we already generate notes */
195
session->no_warnings_for_error= 1;
197
for (table= tables; table; table= table->next_local)
201
error= session->drop_temporary_table(table);
205
// removed temporary table
209
goto err_with_placeholders;
211
// temporary table not found
215
if (drop_temporary == false)
218
abort_locked_tables(session, db, table->table_name);
219
remove_table_from_cache(session, db, table->table_name,
220
RTFC_WAIT_OTHER_THREAD_FLAG |
221
RTFC_CHECK_KILLED_FLAG);
223
If the table was used in lock tables, remember it so that
224
unlock_table_names can free it
226
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
227
table->table= locked_table;
232
goto err_with_placeholders;
235
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : STANDARD_TABLE);
237
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
239
// Table was not found on disk and table can't be created from engine
241
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
242
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
176
// temporary table not found
249
error= plugin::StorageEngine::dropTable(*session, identifier);
251
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
180
if (drop_temporary == false)
183
abort_locked_tables(session, tmp_identifier);
184
table::Cache::singleton().removeTable(session, tmp_identifier,
185
RTFC_WAIT_OTHER_THREAD_FLAG |
186
RTFC_CHECK_KILLED_FLAG);
188
If the table was used in lock tables, remember it so that
189
unlock_table_names can free it
191
if ((locked_table= drop_locked_tables(session, tmp_identifier)))
192
table->table= locked_table;
194
if (session->getKilled())
200
identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
202
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
// Table was not found on disk and table can't be created from engine
206
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
table->getTableName());
216
drizzled::error_t local_error;
218
/* Generate transaction event ONLY when we successfully drop */
219
if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
221
TransactionServices &transaction_services= TransactionServices::singleton();
222
transaction_services.dropTable(*session, identifier, if_exists);
226
if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
229
session->clear_error();
232
if (local_error == HA_ERR_ROW_IS_REFERENCED)
234
/* the table is referenced by a foreign key constraint */
235
foreign_key_error= true;
243
if (wrong_tables.length())
244
wrong_tables.append(',');
245
wrong_tables.append(String(table->getTableName(), system_charset_info));
249
tables->unlock_table_names();
254
session->clear_error();
257
if (error == HA_ERR_ROW_IS_REFERENCED)
259
/* the table is referenced by a foreign key constraint */
260
foreign_key_error= true;
264
if (error == 0 || (if_exists && foreign_key_error == false))
266
ReplicationServices &replication_services= ReplicationServices::singleton();
267
replication_services.dropTable(session, string(db), string(table->table_name), if_exists);
272
if (wrong_tables.length())
273
wrong_tables.append(',');
274
wrong_tables.append(String(table->table_name,system_charset_info));
278
It's safe to unlock LOCK_open: we have an exclusive lock
281
pthread_mutex_unlock(&LOCK_open);
253
283
if (wrong_tables.length())
255
if (not foreign_key_error)
285
if (!foreign_key_error)
257
286
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
287
wrong_tables.c_ptr());
262
290
my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
493
514
(*timestamps_with_niladic)++;
497
517
sql_field->unireg_check= Field::NONE;
500
519
else if (sql_field->unireg_check != Field::NONE)
502
520
(*timestamps_with_niladic)++;
509
case DRIZZLE_TYPE_BOOLEAN:
510
case DRIZZLE_TYPE_DATE: // Rest of string types
511
case DRIZZLE_TYPE_DATETIME:
512
case DRIZZLE_TYPE_DECIMAL:
513
case DRIZZLE_TYPE_DOUBLE:
514
case DRIZZLE_TYPE_LONG:
515
case DRIZZLE_TYPE_LONGLONG:
516
case DRIZZLE_TYPE_NULL:
517
case DRIZZLE_TYPE_TIME:
518
case DRIZZLE_TYPE_UUID:
519
case DRIZZLE_TYPE_VARCHAR:
525
sql_field->pack_flag=(0 |
526
f_settype((uint32_t) sql_field->sql_type));
526
static int prepare_create_table(Session *session,
527
HA_CREATE_INFO *create_info,
528
message::Table &create_proto,
529
AlterInfo *alter_info,
531
uint32_t *db_options,
532
KeyInfo **key_info_buffer,
534
int select_field_count)
532
static int mysql_prepare_create_table(Session *session,
533
HA_CREATE_INFO *create_info,
534
message::Table &create_proto,
535
AlterInfo *alter_info,
537
uint32_t *db_options,
538
KEY **key_info_buffer,
540
int select_field_count)
536
542
const char *key_name;
537
543
CreateField *sql_field,*dup_field;
538
544
uint field,null_fields,blob_columns,max_key_length;
539
545
ulong record_offset= 0;
541
KeyPartInfo *key_part_info;
547
KEY_PART_INFO *key_part_info;
542
548
int timestamps= 0, timestamps_with_niladic= 0;
544
550
int select_field_pos,auto_increment=0;
545
551
List_iterator<CreateField> it(alter_info->create_list);
546
552
List_iterator<CreateField> it2(alter_info->create_list);
1297
static bool locked_create_event(Session *session,
1298
const identifier::Table &identifier,
1299
HA_CREATE_INFO *create_info,
1300
message::Table &table_proto,
1301
AlterInfo *alter_info,
1302
bool is_if_not_exists,
1303
bool internal_tmp_table,
1306
KeyInfo *key_info_buffer)
1313
@note if we are building a temp table we need to check to see if a temp table
1314
already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1315
to create a table under a temporary table.
1318
plugin::StorageEngine::doesTableExist(*session, identifier,
1319
identifier.getType() != message::Table::STANDARD );
1323
if (is_if_not_exists)
1326
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1327
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1328
identifier.getTableName().c_str());
1329
create_info->table_existed= 1; // Mark that table existed
1333
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1338
if (identifier.getType() == message::Table::STANDARD) // We have a real table
1341
We don't assert here, but check the result, because the table could be
1342
in the table definition cache and in the same time the .frm could be
1343
missing from the disk, in case of manual intervention which deletes
1344
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1345
Then she could create the table. This case is pretty obscure and
1346
therefore we don't introduce a new error message only for it.
1349
@todo improve this error condition.
1351
if (definition::Cache::singleton().find(identifier.getKey()))
1353
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1360
session->set_proc_info("creating table");
1361
create_info->table_existed= 0; // Mark that table is created
1363
create_info->table_options= db_options;
1365
if (not rea_create_table(session, identifier,
1367
create_info, alter_info->create_list,
1368
key_count, key_info_buffer))
1373
if (identifier.getType() == message::Table::TEMPORARY)
1375
/* Open table and put in temporary table list */
1376
if (not (session->open_temporary_table(identifier)))
1378
(void) session->rm_temporary_table(identifier);
1384
We keep this behind the lock to make sure ordering is correct for a table.
1385
This is a very unlikely problem where before we would write out to the
1386
trans log, someone would do a delete/create operation.
1389
if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1391
TransactionServices &transaction_services= TransactionServices::singleton();
1392
transaction_services.createTable(*session, table_proto);
1400
1282
Ignore the name of this function... it locks :(
1449
assert(identifier.getTableName() == table_proto.name());
1334
assert(strcmp(identifier.getTableName(), table_proto.name().c_str())==0);
1450
1335
db_options= create_info->table_options;
1452
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1454
/* Build a Table object to pass down to the engine, and the do the actual create. */
1455
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1458
&key_info_buffer, &key_count,
1459
select_field_count))
1461
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
error= locked_create_event(session,
1469
db_options, key_count,
1473
session->set_proc_info("After create");
1479
@note the following two methods implement create [temporary] table.
1481
static bool drizzle_create_table(Session *session,
1482
const identifier::Table &identifier,
1483
HA_CREATE_INFO *create_info,
1484
message::Table &table_proto,
1485
AlterInfo *alter_info,
1486
bool internal_tmp_table,
1487
uint32_t select_field_count,
1488
bool is_if_not_exists)
1490
Table *name_lock= NULL;
1493
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1497
else if (name_lock == NULL)
1337
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1338
db_options|=HA_OPTION_PACK_RECORD;
1340
set_table_default_charset(create_info, identifier.getDBName());
1342
/* Check if table exists */
1343
if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1346
&key_info_buffer, &key_count,
1347
select_field_count))
1350
/* Check if table already exists */
1351
if (lex_identified_temp_table &&
1352
session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1499
1354
if (is_if_not_exists)
1356
create_info->table_existed= 1; // Mark that table existed
1501
1357
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
1358
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1503
identifier.getTableName().c_str());
1504
create_info->table_existed= 1;
1509
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1515
result= create_table_no_lock(session,
1527
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1528
session->unlink_open_table(name_lock);
1359
identifier.getTableName());
1363
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1367
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1368
if (not internal_tmp_table && not lex_identified_temp_table)
1370
if (plugin::StorageEngine::doesTableExist(*session,
1371
identifier, false)==EEXIST)
1373
if (is_if_not_exists)
1376
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1377
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1378
identifier.getTableName());
1379
create_info->table_existed= 1; // Mark that table existed
1383
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1386
goto unlock_and_end;
1389
We don't assert here, but check the result, because the table could be
1390
in the table definition cache and in the same time the .frm could be
1391
missing from the disk, in case of manual intervention which deletes
1392
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1393
Then she could create the table. This case is pretty obscure and
1394
therefore we don't introduce a new error message only for it.
1396
if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
1398
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1399
goto unlock_and_end;
1404
Check that table with given name does not already
1405
exist in any storage engine. In such a case it should
1406
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1407
unless user specified CREATE TABLE IF EXISTS
1408
The LOCK_open mutex has been locked to make sure no
1409
one else is attempting to discover the table. Since
1410
it's not on disk as a frm cursor, no one could be using it!
1412
if (not lex_identified_temp_table)
1414
bool exists= plugin::StorageEngine::doesTableExist(*session, identifier, false);
1418
if (is_if_not_exists)
1421
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1422
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1423
identifier.getTableName());
1424
create_info->table_existed= 1; // Mark that table existed
1425
goto unlock_and_end;
1428
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1429
goto unlock_and_end;
1433
session->set_proc_info("creating table");
1434
create_info->table_existed= 0; // Mark that table is created
1436
create_info->table_options= db_options;
1438
if (rea_create_table(session, identifier,
1440
create_info, alter_info->create_list,
1441
key_count, key_info_buffer))
1443
goto unlock_and_end;
1446
if (lex_identified_temp_table)
1448
/* Open table and put in temporary table list */
1449
if (not (session->open_temporary_table(identifier)))
1451
(void) session->rm_temporary_table(identifier);
1452
goto unlock_and_end;
1456
if (not internal_tmp_table && not lex_identified_temp_table)
1458
ReplicationServices &replication_services= ReplicationServices::singleton();
1459
replication_services.createTable(session, table_proto);
1463
pthread_mutex_unlock(&LOCK_open);
1466
session->set_proc_info("After create");
1536
Database locking aware wrapper for create_table_no_lock(),
1473
Database locking aware wrapper for mysql_create_table_no_lock(),
1538
bool create_table(Session *session,
1539
const identifier::Table &identifier,
1476
bool mysql_create_table(Session *session,
1477
TableIdentifier &identifier,
1540
1478
HA_CREATE_INFO *create_info,
1541
1479
message::Table &table_proto,
1542
1480
AlterInfo *alter_info,
1544
1482
uint32_t select_field_count,
1545
1483
bool is_if_not_exists)
1547
if (identifier.isTmp())
1549
return create_table_no_lock(session,
1559
return drizzle_create_table(session,
1485
Table *name_lock= NULL;
1487
bool lex_identified_temp_table=
1488
(table_proto.type() == message::Table::TEMPORARY);
1490
if (not lex_identified_temp_table)
1492
if (session->lock_table_name_if_not_cached(identifier.getDBName(),
1493
identifier.getTableName(),
1499
if (name_lock == NULL)
1501
if (is_if_not_exists)
1503
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1504
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1505
identifier.getTableName());
1506
create_info->table_existed= 1;
1511
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1518
result= mysql_create_table_no_lock(session,
1530
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1531
session->unlink_open_table(name_lock);
1532
pthread_mutex_unlock(&LOCK_open);
1633
rename_table(Session &session,
1634
plugin::StorageEngine *base,
1635
const identifier::Table &from,
1636
const identifier::Table &to)
1604
mysql_rename_table(plugin::StorageEngine *base, const char *old_db,
1605
const char *old_name, const char *new_db,
1606
const char *new_name, uint32_t flags)
1608
Session *session= current_session;
1609
char from[FN_REFLEN], to[FN_REFLEN];
1610
char *from_base= from, *to_base= to;
1642
if (not plugin::StorageEngine::doesSchemaExist(to))
1615
build_table_filename(from, sizeof(from), old_db, old_name,
1616
flags & FN_FROM_IS_TMP);
1617
build_table_filename(to, sizeof(to), new_db, new_name,
1618
flags & FN_TO_IS_TMP);
1620
if (!(error= base->renameTable(session, from_base, to_base)))
1644
my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1622
if (base->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == 0
1623
&& rename_table_proto_file(from_base, to_base))
1626
base->renameTable(session, to_base, from_base);
1648
error= base->renameTable(session, from, to);
1650
1630
if (error == HA_ERR_WRONG_COMMAND)
1652
1631
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1654
1632
else if (error)
1656
std::string from_path;
1657
std::string to_path;
1659
from.getSQLPath(from_path);
1660
to.getSQLPath(to_path);
1662
const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1663
const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1665
my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1668
return error ? true : false;
1633
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
1828
1797
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1798
uint32_t length;
1830
session->getClient()->store(table_name);
1831
session->getClient()->store(operator_name);
1832
session->getClient()->store(STRING_WITH_LEN("error"));
1799
session->client->store(table_name);
1800
session->client->store(operator_name);
1801
session->client->store(STRING_WITH_LEN("error"));
1833
1802
length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1835
session->getClient()->store(buff, length);
1836
transaction_services.autocommitOrRollback(*session, false);
1804
session->client->store(buff, length);
1805
transaction_services.ha_autocommit_or_rollback(session, false);
1837
1806
session->endTransaction(COMMIT);
1838
1807
session->close_thread_tables();
1839
1808
lex->reset_query_tables_list(false);
1840
1809
table->table=0; // For query cache
1841
if (session->getClient()->flush())
1810
if (session->client->flush())
1846
1815
/* Close all instances of the table to allow repair to rename files */
1847
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1816
if (lock_type == TL_WRITE && table->table->s->version)
1849
table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1850
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1851
"Waiting to get writelock");
1852
session->abortLock(table->table);
1853
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1818
pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
1819
const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1820
"Waiting to get writelock");
1821
mysql_lock_abort(session,table->table);
1822
remove_table_from_cache(session, table->table->s->db.str,
1823
table->table->s->table_name.str,
1824
RTFC_WAIT_OTHER_THREAD_FLAG |
1825
RTFC_CHECK_KILLED_FLAG);
1855
1826
session->exit_cond(old_message);
1856
if (session->getKilled())
1827
if (session->killed)
1858
1829
open_for_modify= 0;
1888
1859
char buf[ERRMSGSIZE+20];
1889
1860
uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
1861
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
session->getClient()->store(STRING_WITH_LEN("note"));
1892
session->getClient()->store(buf, length);
1862
session->client->store(STRING_WITH_LEN("note"));
1863
session->client->store(buf, length);
1896
1867
case HA_ADMIN_OK:
1897
session->getClient()->store(STRING_WITH_LEN("status"));
1898
session->getClient()->store(STRING_WITH_LEN("OK"));
1868
session->client->store(STRING_WITH_LEN("status"));
1869
session->client->store(STRING_WITH_LEN("OK"));
1901
1872
case HA_ADMIN_FAILED:
1902
session->getClient()->store(STRING_WITH_LEN("status"));
1903
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1873
session->client->store(STRING_WITH_LEN("status"));
1874
session->client->store(STRING_WITH_LEN("Operation failed"));
1906
1877
case HA_ADMIN_REJECT:
1907
session->getClient()->store(STRING_WITH_LEN("status"));
1908
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1878
session->client->store(STRING_WITH_LEN("status"));
1879
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
1880
open_for_modify= false;
1912
1883
case HA_ADMIN_ALREADY_DONE:
1913
session->getClient()->store(STRING_WITH_LEN("status"));
1914
session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
1884
session->client->store(STRING_WITH_LEN("status"));
1885
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1917
1888
case HA_ADMIN_CORRUPT:
1918
session->getClient()->store(STRING_WITH_LEN("error"));
1919
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1889
session->client->store(STRING_WITH_LEN("error"));
1890
session->client->store(STRING_WITH_LEN("Corrupt"));
1923
1894
case HA_ADMIN_INVALID:
1924
session->getClient()->store(STRING_WITH_LEN("error"));
1925
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1895
session->client->store(STRING_WITH_LEN("error"));
1896
session->client->store(STRING_WITH_LEN("Invalid argument"));
1928
1899
default: // Probably HA_ADMIN_INTERNAL_ERROR
1940
1911
if (table->table)
1942
1913
if (fatal_error)
1944
table->table->getMutableShare()->resetVersion(); // Force close of table
1914
table->table->s->version=0; // Force close of table
1946
1915
else if (open_for_modify)
1948
if (table->table->getShare()->getType())
1917
if (table->table->s->tmp_table)
1950
1918
table->table->cursor->info(HA_STATUS_CONST);
1954
boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1955
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1956
table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1921
pthread_mutex_lock(&LOCK_open);
1922
remove_table_from_cache(session, table->table->s->db.str,
1923
table->table->s->table_name.str, RTFC_NO_FLAG);
1924
pthread_mutex_unlock(&LOCK_open);
1960
transaction_services.autocommitOrRollback(*session, false);
1928
transaction_services.ha_autocommit_or_rollback(session, false);
1961
1929
session->endTransaction(COMMIT);
1962
1930
session->close_thread_tables();
1963
1931
table->table=0; // For query cache
1964
if (session->getClient()->flush())
1932
if (session->client->flush())
1949
We have to write the query before we unlock the named table.
1951
Since temporary tables are not replicated under row-based
1952
replication, CREATE TABLE ... LIKE ... needs special
1953
treatement. We have four cases to consider, according to the
1954
following decision table:
1956
==== ========= ========= ==============================
1957
Case Target Source Write to binary log
1958
==== ========= ========= ==============================
1959
1 normal normal Original statement
1960
2 normal temporary Generated statement
1961
3 temporary normal Nothing
1962
4 temporary temporary Nothing
1963
==== ========= ========= ==============================
1965
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
1966
bool is_src_table_tmp, bool is_if_not_exists)
1968
if (is_src_table_tmp)
1971
String query(buf, sizeof(buf), system_charset_info);
1972
query.length(0); // Have to zero it since constructor doesn't
1976
Here we open the destination table, on which we already have
1977
name-lock. This is needed for store_create_info() to work.
1978
The table will be closed by unlink_open_table() at the end
1981
table->table= name_lock;
1982
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
1983
if (session->reopen_name_locked_table(table, false))
1985
pthread_mutex_unlock(&LOCK_open);
1988
pthread_mutex_unlock(&LOCK_open);
1990
int result= store_create_info(table, &query, is_if_not_exists);
1992
assert(result == 0); // store_create_info() always return 0
1993
write_bin_log(session, query.ptr());
1997
write_bin_log(session, session->query.c_str());
1981
2004
Create a new table by copying from source table
1983
2006
Altough exclusive name-lock on target table protects us from concurrent
1984
2007
DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2008
to plugin::StorageEngine::createTable() in critical section protected by
1986
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2009
LOCK_open in order to provide minimal atomicity against operations which
1987
2010
disregard name-locks, like I_S implementation, for example. This is a
1988
2011
temporary and should not be copied. Instead we should fix our code to
1989
2012
always honor name-locks.
1991
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2014
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2015
during the call to plugin::StorageEngine::createTable().
1993
2016
See bug #28614 for more info.
1995
static bool create_table_wrapper(Session &session,
1996
const message::Table& create_table_proto,
1997
identifier::Table::const_reference destination_identifier,
1998
identifier::Table::const_reference source_identifier,
2018
static bool create_table_wrapper(Session &session, message::Table& create_table_proto,
2019
TableIdentifier &destination_identifier,
2020
TableIdentifier &src_table,
2021
bool lex_identified_temp_table, bool is_engine_set)
2001
// We require an additional table message because during parsing we used
2002
// a "new" message and it will not have all of the information that the
2003
// source table message would have.
2004
message::Table new_table_message;
2005
drizzled::error_t error;
2007
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2009
if (not source_table_message)
2011
my_error(ER_TABLE_UNKNOWN, source_identifier);
2023
int protoerr= EEXIST;
2024
message::Table new_proto;
2025
message::Table src_proto;
2027
protoerr= plugin::StorageEngine::getTableDefinition(session,
2030
new_proto.CopyFrom(src_proto);
2032
if (lex_identified_temp_table)
2034
new_proto.set_type(message::Table::TEMPORARY);
2038
new_proto.set_type(message::Table::STANDARD);
2043
message::Table::StorageEngine *protoengine;
2045
protoengine= new_proto.mutable_engine();
2046
protoengine->set_name(create_table_proto.engine().name());
2049
if (protoerr && protoerr != EEXIST)
2051
if (errno == ENOENT)
2052
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName());
2054
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), errno);
2015
new_table_message.CopyFrom(*source_table_message);
2017
if (destination_identifier.isTmp())
2019
new_table_message.set_type(message::Table::TEMPORARY);
2023
new_table_message.set_type(message::Table::STANDARD);
2028
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2031
{ // We now do a selective copy of elements on to the new table.
2032
new_table_message.set_name(create_table_proto.name());
2033
new_table_message.set_schema(create_table_proto.schema());
2034
new_table_message.set_catalog(create_table_proto.catalog());
2037
/* Fix names of foreign keys being added */
2038
for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2040
if (new_table_message.fk_constraint(j).has_name())
2042
std::string name(new_table_message.name());
2045
name.append("_ibfk_");
2046
snprintf(number, sizeof(number), "%d", j+1);
2047
name.append(number);
2049
message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
pfkey->set_name(name);
2055
2060
As mysql_truncate don't work on a new table at this stage of
2056
creation, instead create the table directly (for both normal and temporary tables).
2061
creation, instead create the table directly (for both normal
2062
and temporary tables).
2058
bool success= plugin::StorageEngine::createTable(session,
2059
destination_identifier,
2062
if (success && not destination_identifier.isTmp())
2064
TransactionServices &transaction_services= TransactionServices::singleton();
2065
transaction_services.createTable(session, new_table_message);
2064
int err= plugin::StorageEngine::createTable(session,
2065
destination_identifier,
2068
return err ? false : true;
2072
2072
Create a table identical to the specified table
2075
mysql_create_like_table()
2076
2076
session Thread object
2077
2077
table Table list element for target table
2078
2078
src_table Table list element for source table
2086
bool create_like_table(Session* session,
2087
identifier::Table::const_reference destination_identifier,
2088
identifier::Table::const_reference source_identifier,
2089
message::Table &create_table_proto,
2090
bool is_if_not_exists,
2086
bool mysql_create_like_table(Session* session,
2087
TableIdentifier &destination_identifier,
2088
TableList* table, TableList* src_table,
2089
message::Table& create_table_proto,
2090
bool is_if_not_exists,
2093
Table *name_lock= 0;
2094
char *db= table->db;
2095
char *table_name= table->table_name;
2093
2096
bool res= true;
2094
bool table_exists= false;
2098
bool lex_identified_temp_table=
2099
(create_table_proto.type() == message::Table::TEMPORARY);
2103
By opening source table we guarantee that it exists and no concurrent
2104
DDL operation will mess with it. Later we also take an exclusive
2105
name-lock on target table name, which makes copying of .frm cursor,
2106
call to plugin::StorageEngine::createTable() and binlogging atomic
2107
against concurrent DML and DDL operations on target table.
2108
Thus by holding both these "locks" we ensure that our statement is
2109
properly isolated from all concurrent operations which matter.
2111
if (session->open_tables_from_list(&src_table, ¬_used))
2114
TableIdentifier src_identifier(src_table->table->s->db.str,
2115
src_table->table->s->table_name.str, src_table->table->s->tmp_table);
2097
2120
Check that destination tables does not exist. Note that its name
2098
2121
was already checked when it was added to the table list.
2100
For temporary tables we don't aim to grab locks.
2102
if (destination_identifier.isTmp())
2123
bool table_exists= false;
2124
if (lex_identified_temp_table)
2104
if (session->find_temporary_table(destination_identifier))
2126
if (session->find_temporary_table(db, table_name))
2106
2128
table_exists= true;
2110
bool was_created= create_table_wrapper(*session,
2112
destination_identifier,
2115
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2117
(void) session->rm_temporary_table(destination_identifier, true);
2119
else if (not session->open_temporary_table(destination_identifier))
2121
// We created, but we can't open... also, a hack.
2122
(void) session->rm_temporary_table(destination_identifier, true);
2130
else // Standard table which will require locks.
2132
Table *name_lock= 0;
2134
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2133
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2138
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2137
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2139
2138
session->unlink_open_table(name_lock);
2139
pthread_mutex_unlock(&LOCK_open);
2185
2159
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
2160
snprintf(warn_buff, sizeof(warn_buff),
2187
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2161
ER(ER_TABLE_EXISTS_ERROR), table_name);
2188
2162
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
ER_TABLE_EXISTS_ERROR, warn_buff);
2193
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2163
ER_TABLE_EXISTS_ERROR,warn_buff);
2168
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2171
else // Otherwise we create the table
2173
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2174
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2175
src_identifier, lex_identified_temp_table, is_engine_set);
2176
pthread_mutex_unlock(&LOCK_open);
2178
// So we blew the creation of the table, and we scramble to clean up
2179
// anything that might have been created (read... it is a hack)
2180
if (not was_created)
2182
if (lex_identified_temp_table)
2184
(void) session->rm_temporary_table(destination_identifier);
2188
quick_rm_table(*session, destination_identifier);
2191
else if (lex_identified_temp_table && not session->open_temporary_table(destination_identifier))
2193
// We created, but we can't open... also, a hack.
2194
(void) session->rm_temporary_table(destination_identifier);
2198
if (not lex_identified_temp_table)
2200
bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
2210
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2211
session->unlink_open_table(name_lock);
2212
pthread_mutex_unlock(&LOCK_open);
2202
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2219
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2204
2221
thr_lock_type lock_type = TL_READ_NO_INSERT;
2206
return(admin_table(session, tables, check_opt,
2223
return(mysql_admin_table(session, tables, check_opt,
2207
2224
"analyze", lock_type, true,
2208
2225
&Cursor::ha_analyze));
2212
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2229
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2214
2231
thr_lock_type lock_type = TL_READ_NO_INSERT;
2216
return(admin_table(session, tables, check_opt,
2233
return(mysql_admin_table(session, tables, check_opt,
2217
2234
"check", lock_type,
2219
2236
&Cursor::ha_check));
2240
bool mysql_checksum_table(Session *session, TableList *tables,
2244
List<Item> field_list;
2247
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2248
item->maybe_null= 1;
2249
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2250
MY_INT64_NUM_DECIMAL_DIGITS));
2251
item->maybe_null= 1;
2252
if (session->client->sendFields(&field_list))
2255
/* Open one table after the other to keep lock time as short as possible. */
2256
for (table= tables; table; table= table->next_local)
2258
char table_name[NAME_LEN*2+2];
2261
sprintf(table_name,"%s.%s",table->db,table->table_name);
2263
t= table->table= session->openTableLock(table, TL_READ);
2264
session->clear_error(); // these errors shouldn't get client
2266
session->client->store(table_name);
2270
/* Table didn't exist */
2271
session->client->store();
2272
session->clear_error();
2277
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2279
if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
2281
session->client->store((uint64_t)t->cursor->checksum());
2285
/* calculating table's checksum */
2286
internal::ha_checksum crc= 0;
2287
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2289
t->use_all_columns();
2291
if (t->cursor->ha_rnd_init(1))
2292
session->client->store();
2297
internal::ha_checksum row_crc= 0;
2298
int error= t->cursor->rnd_next(t->record[0]);
2299
if (unlikely(error))
2301
if (error == HA_ERR_RECORD_DELETED)
2305
if (t->s->null_bytes)
2307
/* fix undefined null bits */
2308
t->record[0][t->s->null_bytes-1] |= null_mask;
2309
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2310
t->record[0][0] |= 1;
2312
row_crc= internal::my_checksum(row_crc, t->record[0], t->s->null_bytes);
2315
for (uint32_t i= 0; i < t->s->fields; i++ )
2317
Field *f= t->field[i];
2318
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2319
(f->type() == DRIZZLE_TYPE_VARCHAR))
2323
row_crc= internal::my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2326
row_crc= internal::my_checksum(row_crc, f->ptr,
2332
session->client->store((uint64_t)crc);
2333
t->cursor->ha_rnd_end();
2336
session->clear_error();
2337
session->close_thread_tables();
2338
table->table=0; // For query cache
2340
if (session->client->flush())
2348
session->close_thread_tables(); // Shouldn't be needed
2222
2354
} /* namespace drizzled */