110
void write_bin_log(Session *session, const std::string &query)
106
void write_bin_log(Session *session,
112
109
TransactionServices &transaction_services= TransactionServices::singleton();
113
110
transaction_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
TransactionServices &transaction_services= TransactionServices::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
transaction_services.rawStatement(session, built_query);
117
138
Execute the drop of a normal or temporary table
149
170
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
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)
182
TableIdentifier identifier(table->db, table->table_name);
184
table->db_type= NULL;
186
if ((share= TableShare::getShare(identifier)))
188
table->db_type= share->db_type();
192
if (not drop_temporary && lock_table_names_exclusively(session, tables))
194
pthread_mutex_unlock(&LOCK_open);
198
/* Don't give warnings for not found errors, as we already generate notes */
199
session->no_warnings_for_error= 1;
201
for (table= tables; table; table= table->next_local)
205
error= session->drop_temporary_table(table);
209
// removed temporary table
213
goto err_with_placeholders;
215
// temporary table not found
219
if (drop_temporary == false)
222
abort_locked_tables(session, db, table->table_name);
223
remove_table_from_cache(session, db, table->table_name,
224
RTFC_WAIT_OTHER_THREAD_FLAG |
225
RTFC_CHECK_KILLED_FLAG);
227
If the table was used in lock tables, remember it so that
228
unlock_table_names can free it
230
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
231
table->table= locked_table;
236
goto err_with_placeholders;
239
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? message::Table::INTERNAL : message::Table::STANDARD);
241
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
243
// Table was not found on disk and table can't be created from engine
245
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
246
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
175
goto err_with_placeholders;
177
// temporary table not found
253
error= plugin::StorageEngine::dropTable(*session, identifier);
255
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
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();
258
session->clear_error();
261
if (error == HA_ERR_ROW_IS_REFERENCED)
263
/* the table is referenced by a foreign key constraint */
264
foreign_key_error= true;
268
if (error == 0 || (if_exists && foreign_key_error == false))
270
TransactionServices &transaction_services= TransactionServices::singleton();
271
transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
276
if (wrong_tables.length())
277
wrong_tables.append(',');
278
wrong_tables.append(String(table->table_name,system_charset_info));
282
It's safe to unlock LOCK_open: we have an exclusive lock
285
pthread_mutex_unlock(&LOCK_open);
251
288
if (wrong_tables.length())
340
class typelib_set_member
344
const CHARSET_INFO * const cs;
346
typelib_set_member(const char* value, unsigned int length,
347
const CHARSET_INFO * const charset)
353
static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
355
return (my_strnncoll(a.cs,
356
(const unsigned char*)a.s.c_str(), a.s.length(),
357
(const unsigned char*)b.s.c_str(), b.s.length())==0);
363
class typelib_set_member_hasher
365
boost::hash<string> hasher;
367
std::size_t operator()(const typelib_set_member& t) const
374
398
static bool check_duplicates_in_interval(const char *set_or_name,
375
399
const char *name, TYPELIB *typelib,
376
400
const CHARSET_INFO * const cs,
1423
1425
assert(identifier.getTableName() == table_proto.name());
1424
1426
db_options= create_info->table_options;
1428
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1429
db_options|=HA_OPTION_PACK_RECORD;
1426
1431
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1428
1433
/* Build a Table object to pass down to the engine, and the do the actual create. */
1429
1434
if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1432
&key_info_buffer, &key_count,
1433
select_field_count))
1437
&key_info_buffer, &key_count,
1438
select_field_count))
1435
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1440
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1436
1441
error= locked_create_event(session,
1822
1823
/* Close all instances of the table to allow repair to rename files */
1823
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1824
if (lock_type == TL_WRITE && table->table->getShare()->version)
1825
table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1826
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1827
"Waiting to get writelock");
1828
session->abortLock(table->table);
1829
TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1830
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1826
pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
1827
const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1828
"Waiting to get writelock");
1829
mysql_lock_abort(session,table->table);
1830
remove_table_from_cache(session, table->table->getMutableShare()->getSchemaName(),
1831
table->table->getMutableShare()->getTableName(),
1832
RTFC_WAIT_OTHER_THREAD_FLAG |
1833
RTFC_CHECK_KILLED_FLAG);
1831
1834
session->exit_cond(old_message);
1832
if (session->getKilled())
1835
if (session->killed)
1834
1837
open_for_modify= 0;
1957
We have to write the query before we unlock the named table.
1959
Since temporary tables are not replicated under row-based
1960
replication, CREATE TABLE ... LIKE ... needs special
1961
treatement. We have four cases to consider, according to the
1962
following decision table:
1964
==== ========= ========= ==============================
1965
Case Target Source Write to binary log
1966
==== ========= ========= ==============================
1967
1 normal normal Original statement
1968
2 normal temporary Generated statement
1969
3 temporary normal Nothing
1970
4 temporary temporary Nothing
1971
==== ========= ========= ==============================
1973
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
1974
bool is_src_table_tmp, bool is_if_not_exists)
1976
if (is_src_table_tmp)
1979
String query(buf, sizeof(buf), system_charset_info);
1980
query.length(0); // Have to zero it since constructor doesn't
1984
Here we open the destination table, on which we already have
1985
name-lock. This is needed for store_create_info() to work.
1986
The table will be closed by unlink_open_table() at the end
1989
table->table= name_lock;
1990
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
1991
if (session->reopen_name_locked_table(table, false))
1993
pthread_mutex_unlock(&LOCK_open);
1996
pthread_mutex_unlock(&LOCK_open);
1998
int result= store_create_info(table, &query, is_if_not_exists);
2000
assert(result == 0); // store_create_info() always return 0
2001
write_bin_log(session, query.ptr());
2005
write_bin_log(session, session->query.c_str());
1957
2012
Create a new table by copying from source table
1959
2014
Altough exclusive name-lock on target table protects us from concurrent
1960
2015
DML and DDL operations on it we still want to wrap .FRM creation and call
1961
2016
to plugin::StorageEngine::createTable() in critical section protected by
1962
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2017
LOCK_open in order to provide minimal atomicity against operations which
1963
2018
disregard name-locks, like I_S implementation, for example. This is a
1964
2019
temporary and should not be copied. Instead we should fix our code to
1965
2020
always honor name-locks.
1967
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2022
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1968
2023
during the call to plugin::StorageEngine::createTable().
1969
2024
See bug #28614 for more info.
1971
2026
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
const TableIdentifier &destination_identifier,
1973
const TableIdentifier &src_table,
2027
TableIdentifier &destination_identifier,
2028
TableIdentifier &src_table,
1974
2029
bool is_engine_set)
1976
2031
int protoerr= EEXIST;
1977
2032
message::Table new_proto;
1978
message::table::shared_ptr src_proto;
2033
message::Table src_proto;
1980
2035
protoerr= plugin::StorageEngine::getTableDefinition(session,
1983
new_proto.CopyFrom(*src_proto);
2038
new_proto.CopyFrom(src_proto);
1985
2040
if (destination_identifier.isTmp())
2081
2132
bool table_exists= false;
2082
2133
if (destination_identifier.isTmp())
2084
if (session->find_temporary_table(destination_identifier))
2135
if (session->find_temporary_table(db, table_name))
2086
2137
table_exists= true;
2090
2141
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
src_identifier, is_engine_set);
2142
src_identifier, is_engine_set);
2092
2143
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);
2145
(void) session->rm_temporary_table(destination_identifier);
2096
2147
else if (not session->open_temporary_table(destination_identifier))
2098
2149
// We created, but we can't open... also, a hack.
2099
(void) session->rm_temporary_table(destination_identifier, true);
2150
(void) session->rm_temporary_table(destination_identifier);
2130
2182
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);
2184
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2185
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2186
src_identifier, is_engine_set);
2187
pthread_mutex_unlock(&LOCK_open);
2139
2189
// So we blew the creation of the table, and we scramble to clean up
2140
2190
// anything that might have been created (read... it is a hack)
2141
2191
if (not was_created)
2143
plugin::StorageEngine::dropTable(*session, destination_identifier);
2193
quick_rm_table(*session, destination_identifier);
2197
bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->getShare()->tmp_table), is_if_not_exists);
2153
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2206
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2154
2207
session->unlink_open_table(name_lock);
2208
pthread_mutex_unlock(&LOCK_open);