110
void write_bin_log(Session *session, const std::string &query)
107
void write_bin_log(Session *session,
112
110
TransactionServices &transaction_services= TransactionServices::singleton();
113
111
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);
117
139
Execute the drop of a normal or temporary table
149
171
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
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;
237
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),
175
goto err_with_placeholders;
177
// temporary table not found
254
error= plugin::StorageEngine::dropTable(*session, identifier);
256
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();
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));
283
It's safe to unlock LOCK_open: we have an exclusive lock
286
pthread_mutex_unlock(&LOCK_open);
251
289
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
399
static bool check_duplicates_in_interval(const char *set_or_name,
375
400
const char *name, TYPELIB *typelib,
376
401
const CHARSET_INFO * const cs,
1423
1440
assert(identifier.getTableName() == table_proto.name());
1424
1441
db_options= create_info->table_options;
1443
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1444
db_options|=HA_OPTION_PACK_RECORD;
1426
1446
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1428
1448
/* Build a Table object to pass down to the engine, and the do the actual create. */
1429
1449
if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1432
&key_info_buffer, &key_count,
1433
select_field_count))
1452
&key_info_buffer, &key_count,
1453
select_field_count))
1435
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1455
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1436
1456
error= locked_create_event(session,
1822
1842
/* Close all instances of the table to allow repair to rename files */
1823
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1843
if (lock_type == TL_WRITE && table->table->s->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);
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);
1831
1853
session->exit_cond(old_message);
1832
if (session->getKilled())
1854
if (session->killed)
1834
1856
open_for_modify= 0;
1916
1938
if (table->table)
1918
1940
if (fatal_error)
1920
table->table->getMutableShare()->resetVersion(); // Force close of table
1941
table->table->s->version=0; // Force close of table
1922
1942
else if (open_for_modify)
1924
if (table->table->getShare()->getType())
1944
if (table->table->s->tmp_table)
1926
1945
table->table->cursor->info(HA_STATUS_CONST);
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);
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);
1936
transaction_services.autocommitOrRollback(session, false);
1955
transaction_services.ha_autocommit_or_rollback(session, false);
1937
1956
session->endTransaction(COMMIT);
1938
1957
session->close_thread_tables();
1939
1958
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());
1957
2031
Create a new table by copying from source table
1959
2033
Altough exclusive name-lock on target table protects us from concurrent
1960
2034
DML and DDL operations on it we still want to wrap .FRM creation and call
1961
2035
to plugin::StorageEngine::createTable() in critical section protected by
1962
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2036
LOCK_open in order to provide minimal atomicity against operations which
1963
2037
disregard name-locks, like I_S implementation, for example. This is a
1964
2038
temporary and should not be copied. Instead we should fix our code to
1965
2039
always honor name-locks.
1967
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2041
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1968
2042
during the call to plugin::StorageEngine::createTable().
1969
2043
See bug #28614 for more info.
1971
2045
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
const TableIdentifier &destination_identifier,
1973
const TableIdentifier &src_table,
2046
TableIdentifier &destination_identifier,
2047
TableIdentifier &src_table,
1974
2048
bool is_engine_set)
1976
2050
int protoerr= EEXIST;
1977
2051
message::Table new_proto;
1978
message::table::shared_ptr src_proto;
2052
message::Table src_proto;
1980
2054
protoerr= plugin::StorageEngine::getTableDefinition(session,
1983
new_proto.CopyFrom(*src_proto);
2057
new_proto.CopyFrom(src_proto);
1985
2059
if (destination_identifier.isTmp())
2067
2142
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());
2145
TableIdentifier src_identifier(src_table->table->s->getSchemaName(),
2146
src_table->table->s->table_name.str, src_table->table->s->tmp_table);
2076
2151
Check that destination tables does not exist. Note that its name
2077
2152
was already checked when it was added to the table list.
2079
For temporary tables we don't aim to grab locks.
2081
2154
bool table_exists= false;
2082
2155
if (destination_identifier.isTmp())
2084
if (session->find_temporary_table(destination_identifier))
2157
if (session->find_temporary_table(db, table_name))
2086
2159
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.
2109
Table *name_lock= 0;
2111
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2164
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2115
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2168
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2116
2169
session->unlink_open_table(name_lock);
2170
pthread_mutex_unlock(&LOCK_open);
2162
2190
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
2191
snprintf(warn_buff, sizeof(warn_buff),
2164
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2192
ER(ER_TABLE_EXISTS_ERROR), table_name);
2165
2193
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2166
2194
ER_TABLE_EXISTS_ERROR,warn_buff);
2171
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
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);
2196
2267
&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
2199
2385
} /* namespace drizzled */