107
void write_bin_log(Session *session,
110
void write_bin_log(Session *session, const std::string &query)
110
112
TransactionServices &transaction_services= TransactionServices::singleton();
111
113
transaction_services.rawStatement(session, query);
115
/* Should should be refactored to go away */
116
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
118
TransactionServices &transaction_services= TransactionServices::singleton();
122
built_query.append("DROP TABLE IF EXISTS ");
124
built_query.append("DROP TABLE ");
126
built_query.append("`");
127
if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
129
built_query.append(db_name);
130
built_query.append("`.`");
133
built_query.append(table_name);
134
built_query.append("`");
135
transaction_services.rawStatement(session, built_query);
139
117
Execute the drop of a normal or temporary table
171
149
bool foreign_key_error= false;
173
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
176
If we have the table in the definition cache, we don't have to check the
177
.frm cursor to find if the table is a normal table (not view) and what
181
for (table= tables; table; table= table->next_local)
183
TableIdentifier identifier(table->db, table->table_name);
185
table->db_type= NULL;
187
if ((share= TableShare::getShare(identifier)))
189
table->db_type= share->db_type();
193
if (not drop_temporary && lock_table_names_exclusively(session, tables))
195
pthread_mutex_unlock(&LOCK_open);
199
/* Don't give warnings for not found errors, as we already generate notes */
200
session->no_warnings_for_error= 1;
202
for (table= tables; table; table= table->next_local)
206
error= session->drop_temporary_table(table);
210
// removed temporary table
214
goto err_with_placeholders;
216
// temporary table not found
220
if (drop_temporary == false)
223
abort_locked_tables(session, db, table->table_name);
224
remove_table_from_cache(session, db, table->table_name,
225
RTFC_WAIT_OTHER_THREAD_FLAG |
226
RTFC_CHECK_KILLED_FLAG);
228
If the table was used in lock tables, remember it so that
229
unlock_table_names can free it
231
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
232
table->table= locked_table;
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
237
175
goto err_with_placeholders;
240
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? message::Table::INTERNAL : message::Table::STANDARD);
242
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
244
// Table was not found on disk and table can't be created from engine
246
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
247
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
254
error= plugin::StorageEngine::dropTable(*session, identifier);
256
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
177
// temporary table not found
259
session->clear_error();
262
if (error == HA_ERR_ROW_IS_REFERENCED)
264
/* the table is referenced by a foreign key constraint */
265
foreign_key_error= true;
269
if (error == 0 || (if_exists && foreign_key_error == false))
271
TransactionServices &transaction_services= TransactionServices::singleton();
272
transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
277
if (wrong_tables.length())
278
wrong_tables.append(',');
279
wrong_tables.append(String(table->table_name,system_charset_info));
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();
283
It's safe to unlock LOCK_open: we have an exclusive lock
286
pthread_mutex_unlock(&LOCK_open);
289
251
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
399
374
static bool check_duplicates_in_interval(const char *set_or_name,
400
375
const char *name, TYPELIB *typelib,
401
376
const CHARSET_INFO * const cs,
1440
1423
assert(identifier.getTableName() == table_proto.name());
1441
1424
db_options= create_info->table_options;
1443
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1444
db_options|=HA_OPTION_PACK_RECORD;
1446
1426
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1448
1428
/* Build a Table object to pass down to the engine, and the do the actual create. */
1449
1429
if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1452
&key_info_buffer, &key_count,
1453
select_field_count))
1432
&key_info_buffer, &key_count,
1433
select_field_count))
1455
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1435
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1456
1436
error= locked_create_event(session,
1842
1822
/* Close all instances of the table to allow repair to rename files */
1843
if (lock_type == TL_WRITE && table->table->s->version)
1823
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1845
pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
1846
const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1847
"Waiting to get writelock");
1848
mysql_lock_abort(session,table->table);
1849
remove_table_from_cache(session, table->table->s->getSchemaName(),
1850
table->table->s->table_name.str,
1851
RTFC_WAIT_OTHER_THREAD_FLAG |
1852
RTFC_CHECK_KILLED_FLAG);
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);
1853
1831
session->exit_cond(old_message);
1854
if (session->killed)
1832
if (session->getKilled())
1856
1834
open_for_modify= 0;
1938
1916
if (table->table)
1940
1918
if (fatal_error)
1941
table->table->s->version=0; // Force close of table
1920
table->table->getMutableShare()->resetVersion(); // Force close of table
1942
1922
else if (open_for_modify)
1944
if (table->table->s->tmp_table)
1924
if (table->table->getShare()->getType())
1945
1926
table->table->cursor->info(HA_STATUS_CONST);
1948
pthread_mutex_lock(&LOCK_open);
1949
remove_table_from_cache(session, table->table->s->getSchemaName(),
1950
table->table->s->table_name.str, RTFC_NO_FLAG);
1951
pthread_mutex_unlock(&LOCK_open);
1930
boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1931
TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1932
table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1955
transaction_services.ha_autocommit_or_rollback(session, false);
1936
transaction_services.autocommitOrRollback(session, false);
1956
1937
session->endTransaction(COMMIT);
1957
1938
session->close_thread_tables();
1958
1939
table->table=0; // For query cache
1976
We have to write the query before we unlock the named table.
1978
Since temporary tables are not replicated under row-based
1979
replication, CREATE TABLE ... LIKE ... needs special
1980
treatement. We have four cases to consider, according to the
1981
following decision table:
1983
==== ========= ========= ==============================
1984
Case Target Source Write to binary log
1985
==== ========= ========= ==============================
1986
1 normal normal Original statement
1987
2 normal temporary Generated statement
1988
3 temporary normal Nothing
1989
4 temporary temporary Nothing
1990
==== ========= ========= ==============================
1992
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
1993
bool is_src_table_tmp, bool is_if_not_exists)
1995
if (is_src_table_tmp)
1998
String query(buf, sizeof(buf), system_charset_info);
1999
query.length(0); // Have to zero it since constructor doesn't
2003
Here we open the destination table, on which we already have
2004
name-lock. This is needed for store_create_info() to work.
2005
The table will be closed by unlink_open_table() at the end
2008
table->table= name_lock;
2009
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2010
if (session->reopen_name_locked_table(table, false))
2012
pthread_mutex_unlock(&LOCK_open);
2015
pthread_mutex_unlock(&LOCK_open);
2017
int result= store_create_info(table, &query, is_if_not_exists);
2019
assert(result == 0); // store_create_info() always return 0
2020
write_bin_log(session, query.ptr());
2024
write_bin_log(session, session->query.c_str());
2031
1957
Create a new table by copying from source table
2033
1959
Altough exclusive name-lock on target table protects us from concurrent
2034
1960
DML and DDL operations on it we still want to wrap .FRM creation and call
2035
1961
to plugin::StorageEngine::createTable() in critical section protected by
2036
LOCK_open in order to provide minimal atomicity against operations which
1962
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2037
1963
disregard name-locks, like I_S implementation, for example. This is a
2038
1964
temporary and should not be copied. Instead we should fix our code to
2039
1965
always honor name-locks.
2041
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1967
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2042
1968
during the call to plugin::StorageEngine::createTable().
2043
1969
See bug #28614 for more info.
2045
1971
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2046
TableIdentifier &destination_identifier,
2047
TableIdentifier &src_table,
1972
const TableIdentifier &destination_identifier,
1973
const TableIdentifier &src_table,
2048
1974
bool is_engine_set)
2050
1976
int protoerr= EEXIST;
2051
1977
message::Table new_proto;
2052
message::Table src_proto;
1978
message::table::shared_ptr src_proto;
2054
1980
protoerr= plugin::StorageEngine::getTableDefinition(session,
2057
new_proto.CopyFrom(src_proto);
1983
new_proto.CopyFrom(*src_proto);
2059
1985
if (destination_identifier.isTmp())
2142
2067
if (session->open_tables_from_list(&src_table, ¬_used))
2145
TableIdentifier src_identifier(src_table->table->s->getSchemaName(),
2146
src_table->table->s->table_name.str, src_table->table->s->tmp_table);
2070
TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2071
src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2151
2076
Check that destination tables does not exist. Note that its name
2152
2077
was already checked when it was added to the table list.
2079
For temporary tables we don't aim to grab locks.
2154
2081
bool table_exists= false;
2155
2082
if (destination_identifier.isTmp())
2157
if (session->find_temporary_table(db, table_name))
2084
if (session->find_temporary_table(destination_identifier))
2159
2086
table_exists= true;
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.
2164
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2109
Table *name_lock= 0;
2111
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2168
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2115
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2169
2116
session->unlink_open_table(name_lock);
2170
pthread_mutex_unlock(&LOCK_open);
2190
2162
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2191
2163
snprintf(warn_buff, sizeof(warn_buff),
2192
ER(ER_TABLE_EXISTS_ERROR), table_name);
2164
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2193
2165
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2194
2166
ER_TABLE_EXISTS_ERROR,warn_buff);
2199
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2202
else // Otherwise we create the table
2204
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2205
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2206
src_identifier, is_engine_set);
2207
pthread_mutex_unlock(&LOCK_open);
2209
// So we blew the creation of the table, and we scramble to clean up
2210
// anything that might have been created (read... it is a hack)
2211
if (not was_created)
2213
if (destination_identifier.isTmp())
2215
(void) session->rm_temporary_table(destination_identifier);
2219
quick_rm_table(*session, destination_identifier);
2222
else if (destination_identifier.isTmp() && not session->open_temporary_table(destination_identifier))
2224
// We created, but we can't open... also, a hack.
2225
(void) session->rm_temporary_table(destination_identifier);
2229
if (not destination_identifier.isTmp())
2231
bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
2241
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2242
session->unlink_open_table(name_lock);
2243
pthread_mutex_unlock(&LOCK_open);
2171
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2267
2196
&Cursor::ha_check));
2271
bool mysql_checksum_table(Session *session, TableList *tables,
2275
List<Item> field_list;
2278
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2279
item->maybe_null= 1;
2280
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2281
MY_INT64_NUM_DECIMAL_DIGITS));
2282
item->maybe_null= 1;
2283
if (session->client->sendFields(&field_list))
2286
/* Open one table after the other to keep lock time as short as possible. */
2287
for (table= tables; table; table= table->next_local)
2289
char table_name[NAME_LEN*2+2];
2292
sprintf(table_name,"%s.%s",table->db,table->table_name);
2294
t= table->table= session->openTableLock(table, TL_READ);
2295
session->clear_error(); // these errors shouldn't get client
2297
session->client->store(table_name);
2301
/* Table didn't exist */
2302
session->client->store();
2303
session->clear_error();
2308
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2310
if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
2312
session->client->store((uint64_t)t->cursor->checksum());
2316
/* calculating table's checksum */
2317
internal::ha_checksum crc= 0;
2318
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2320
t->use_all_columns();
2322
if (t->cursor->ha_rnd_init(1))
2323
session->client->store();
2328
internal::ha_checksum row_crc= 0;
2329
int error= t->cursor->rnd_next(t->record[0]);
2330
if (unlikely(error))
2332
if (error == HA_ERR_RECORD_DELETED)
2336
if (t->s->null_bytes)
2338
/* fix undefined null bits */
2339
t->record[0][t->s->null_bytes-1] |= null_mask;
2340
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2341
t->record[0][0] |= 1;
2343
row_crc= internal::my_checksum(row_crc, t->record[0], t->s->null_bytes);
2346
for (uint32_t i= 0; i < t->s->fields; i++ )
2348
Field *f= t->field[i];
2349
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2350
(f->type() == DRIZZLE_TYPE_VARCHAR))
2354
row_crc= internal::my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2357
row_crc= internal::my_checksum(row_crc, f->ptr,
2363
session->client->store((uint64_t)crc);
2364
t->cursor->ha_rnd_end();
2367
session->clear_error();
2368
session->close_thread_tables();
2369
table->table=0; // For query cache
2371
if (session->client->flush())
2379
session->close_thread_tables(); // Shouldn't be needed
2385
2199
} /* namespace drizzled */