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>
29
#include "drizzled/strfunc.h"
30
#include <drizzled/db.h>
30
31
#include <drizzled/lock.h>
31
32
#include <drizzled/unireg.h>
32
33
#include <drizzled/item/int.h>
33
34
#include <drizzled/item/empty_string.h>
34
35
#include <drizzled/transaction_services.h>
35
#include <drizzled/transaction_services.h>
36
#include "drizzled/transaction_services.h"
36
37
#include <drizzled/table_proto.h>
37
38
#include <drizzled/plugin/client.h>
38
39
#include <drizzled/identifier.h>
39
#include <drizzled/internal/m_string.h>
40
#include <drizzled/global_charset_info.h>
41
#include <drizzled/charset.h>
43
#include <drizzled/definition/cache.h>
45
#include <drizzled/statement/alter_table.h>
46
#include <drizzled/sql_table.h>
47
#include <drizzled/pthread_globals.h>
48
#include <drizzled/typelib.h>
49
#include <drizzled/plugin/storage_engine.h>
40
#include "drizzled/internal/m_string.h"
41
#include "drizzled/global_charset_info.h"
42
#include "drizzled/charset.h"
45
#include "drizzled/statement/alter_table.h"
46
#include "drizzled/sql_table.h"
47
#include "drizzled/pthread_globals.h"
51
49
#include <algorithm>
108
void write_bin_log(Session *session, const std::string &query)
110
TransactionServices &transaction_services= TransactionServices::singleton();
111
transaction_services.rawStatement(*session, query);
108
void write_bin_log(Session *session,
111
TransactionServices &transaction_services= TransactionServices::singleton();
112
transaction_services.rawStatement(session, query);
116
/* Should should be refactored to go away */
117
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
119
TransactionServices &transaction_services= TransactionServices::singleton();
123
built_query.append("DROP TABLE IF EXISTS ");
125
built_query.append("DROP TABLE ");
127
built_query.append("`");
128
if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
130
built_query.append(db_name);
131
built_query.append("`.`");
134
built_query.append(table_name);
135
built_query.append("`");
136
transaction_services.rawStatement(session, built_query);
115
140
Execute the drop of a normal or temporary table
143
mysql_rm_table_part2()
119
144
session Thread Cursor
120
145
tables Tables to drop
121
146
if_exists If set, don't give an error if table doesn't exists.
122
147
In this case we give an warning of level 'NOTE'
123
148
drop_temporary Only drop temporary tables
126
151
When logging to the binary log, we should log
127
152
tmp_tables and transactional tables as separate statements if we
128
153
are in a transaction; This is needed to get these tables into the
138
163
-1 Thread was killed
141
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
166
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
144
169
TableList *table;
145
util::string::vector wrong_tables;
147
172
bool foreign_key_error= false;
151
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
153
if (not drop_temporary && session->lock_table_names_exclusively(tables))
158
/* Don't give warnings for not found errors, as we already generate notes */
159
session->no_warnings_for_error= 1;
161
for (table= tables; table; table= table->next_local)
163
identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
165
error= session->drop_temporary_table(tmp_identifier);
169
// removed temporary table
174
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
177
If we have the table in the definition cache, we don't have to check the
178
.frm cursor to find if the table is a normal table (not view) and what
182
for (table= tables; table; table= table->next_local)
184
TableIdentifier identifier(table->db, table->table_name);
186
table->setDbType(NULL);
188
if ((share= TableShare::getShare(identifier)))
190
table->setDbType(share->db_type());
194
if (not drop_temporary && lock_table_names_exclusively(session, tables))
196
pthread_mutex_unlock(&LOCK_open);
200
/* Don't give warnings for not found errors, as we already generate notes */
201
session->no_warnings_for_error= 1;
203
for (table= tables; table; table= table->next_local)
207
error= session->drop_temporary_table(table);
211
// removed temporary table
215
goto err_with_placeholders;
217
// temporary table not found
221
if (drop_temporary == false)
224
abort_locked_tables(session, db, table->table_name);
225
TableIdentifier identifier(db, table->table_name);
226
remove_table_from_cache(session, identifier,
227
RTFC_WAIT_OTHER_THREAD_FLAG |
228
RTFC_CHECK_KILLED_FLAG);
230
If the table was used in lock tables, remember it so that
231
unlock_table_names can free it
233
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
234
table->table= locked_table;
239
goto err_with_placeholders;
242
TableIdentifier identifier(db, table->table_name, table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
244
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
246
// Table was not found on disk and table can't be created from engine
248
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
249
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
175
// temporary table not found
256
error= plugin::StorageEngine::dropTable(*session, identifier);
258
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
179
if (drop_temporary == false)
182
abort_locked_tables(session, tmp_identifier);
183
table::Cache::singleton().removeTable(session, tmp_identifier,
184
RTFC_WAIT_OTHER_THREAD_FLAG |
185
RTFC_CHECK_KILLED_FLAG);
187
If the table was used in lock tables, remember it so that
188
unlock_table_names can free it
190
if ((locked_table= drop_locked_tables(session, tmp_identifier)))
191
table->table= locked_table;
193
if (session->getKilled())
199
identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
201
message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
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
208
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
table->getTableName());
219
drizzled::error_t local_error;
221
/* Generate transaction event ONLY when we successfully drop */
222
if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
224
if (message) // If we have no definition, we don't know if the table should have been replicated
226
TransactionServices &transaction_services= TransactionServices::singleton();
227
transaction_services.dropTable(*session, identifier, *message, if_exists);
232
if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
235
session->clear_error();
238
if (local_error == HA_ERR_ROW_IS_REFERENCED)
240
/* the table is referenced by a foreign key constraint */
241
foreign_key_error= true;
249
wrong_tables.push_back(table->getTableName());
253
tables->unlock_table_names();
257
if (wrong_tables.size())
261
session->clear_error();
264
if (error == HA_ERR_ROW_IS_REFERENCED)
266
/* the table is referenced by a foreign key constraint */
267
foreign_key_error= true;
271
if (error == 0 || (if_exists && foreign_key_error == false))
273
TransactionServices &transaction_services= TransactionServices::singleton();
274
transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
279
if (wrong_tables.length())
280
wrong_tables.append(',');
281
wrong_tables.append(String(table->table_name,system_charset_info));
285
It's safe to unlock LOCK_open: we have an exclusive lock
288
pthread_mutex_unlock(&LOCK_open);
291
if (wrong_tables.length())
259
293
if (not foreign_key_error)
261
std::string table_error;
263
for (util::string::vector::iterator iter= wrong_tables.begin();
264
iter != wrong_tables.end();
270
table_error.resize(table_error.size() -1);
272
295
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
table_error.c_str());
296
wrong_tables.c_ptr());
515
565
else if (sql_field->unireg_check != Field::NONE)
517
566
(*timestamps_with_niladic)++;
524
case DRIZZLE_TYPE_BOOLEAN:
525
case DRIZZLE_TYPE_DATE: // Rest of string types
526
case DRIZZLE_TYPE_DATETIME:
527
case DRIZZLE_TYPE_DECIMAL:
528
case DRIZZLE_TYPE_DOUBLE:
529
case DRIZZLE_TYPE_LONG:
530
case DRIZZLE_TYPE_LONGLONG:
531
case DRIZZLE_TYPE_NULL:
532
case DRIZZLE_TYPE_TIME:
533
case DRIZZLE_TYPE_UUID:
534
case DRIZZLE_TYPE_VARCHAR:
541
static int prepare_create_table(Session *session,
542
HA_CREATE_INFO *create_info,
543
message::Table &create_proto,
544
AlterInfo *alter_info,
546
uint32_t *db_options,
547
KeyInfo **key_info_buffer,
549
int select_field_count)
577
static int mysql_prepare_create_table(Session *session,
578
HA_CREATE_INFO *create_info,
579
message::Table &create_proto,
580
AlterInfo *alter_info,
582
uint32_t *db_options,
583
KeyInfo **key_info_buffer,
585
int select_field_count)
551
587
const char *key_name;
552
588
CreateField *sql_field,*dup_field;
1465
1466
assert(identifier.getTableName() == table_proto.name());
1466
1467
db_options= create_info->table_options;
1469
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1470
db_options|=HA_OPTION_PACK_RECORD;
1468
1472
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1470
1474
/* Build a Table object to pass down to the engine, and the do the actual create. */
1471
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1474
&key_info_buffer, &key_count,
1475
select_field_count))
1475
if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1478
&key_info_buffer, &key_count,
1479
select_field_count))
1477
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1481
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1478
1482
error= locked_create_event(session,
1846
1846
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1847
uint32_t length;
1848
session->getClient()->store(table_name.c_str());
1849
session->getClient()->store(operator_name);
1850
session->getClient()->store(STRING_WITH_LEN("error"));
1848
session->client->store(table_name);
1849
session->client->store(operator_name);
1850
session->client->store(STRING_WITH_LEN("error"));
1851
1851
length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
table_name.c_str());
1853
session->getClient()->store(buff, length);
1854
transaction_services.autocommitOrRollback(*session, false);
1853
session->client->store(buff, length);
1854
transaction_services.autocommitOrRollback(session, false);
1855
1855
session->endTransaction(COMMIT);
1856
1856
session->close_thread_tables();
1857
session->getLex()->reset_query_tables_list(false);
1857
lex->reset_query_tables_list(false);
1858
1858
table->table=0; // For query cache
1859
if (session->getClient()->flush())
1859
if (session->client->flush())
1864
1864
/* Close all instances of the table to allow repair to rename files */
1865
1865
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1867
table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1868
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1869
"Waiting to get writelock");
1870
session->abortLock(table->table);
1871
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1867
pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
1868
const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1869
"Waiting to get writelock");
1870
mysql_lock_abort(session,table->table);
1871
TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
1872
remove_table_from_cache(session, identifier,
1873
RTFC_WAIT_OTHER_THREAD_FLAG |
1874
RTFC_CHECK_KILLED_FLAG);
1873
1875
session->exit_cond(old_message);
1874
if (session->getKilled())
1876
if (session->killed)
1876
1878
open_for_modify= 0;
1883
session->getLex()->cleanup_after_one_table_open();
1885
lex->cleanup_after_one_table_open();
1884
1886
session->clear_error(); // these errors shouldn't get client
1886
List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1888
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1889
DRIZZLE_ERROR *err;
1888
1890
while ((err= it++))
1890
session->getClient()->store(table_name.c_str());
1891
session->getClient()->store(operator_name);
1892
session->getClient()->store(warning_level_names[err->level].str,
1892
session->client->store(table_name);
1893
session->client->store(operator_name);
1894
session->client->store(warning_level_names[err->level].str,
1893
1895
warning_level_names[err->level].length);
1894
session->getClient()->store(err->msg);
1895
if (session->getClient()->flush())
1896
session->client->store(err->msg);
1897
if (session->client->flush())
1898
1900
drizzle_reset_errors(session, true);
1900
session->getClient()->store(table_name.c_str());
1901
session->getClient()->store(operator_name);
1902
session->client->store(table_name);
1903
session->client->store(operator_name);
1903
1905
switch (result_code) {
1904
1906
case HA_ADMIN_NOT_IMPLEMENTED:
1906
1908
char buf[ERRMSGSIZE+20];
1907
1909
uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1910
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
session->getClient()->store(STRING_WITH_LEN("note"));
1910
session->getClient()->store(buf, length);
1911
session->client->store(STRING_WITH_LEN("note"));
1912
session->client->store(buf, length);
1914
1916
case HA_ADMIN_OK:
1915
session->getClient()->store(STRING_WITH_LEN("status"));
1916
session->getClient()->store(STRING_WITH_LEN("OK"));
1917
session->client->store(STRING_WITH_LEN("status"));
1918
session->client->store(STRING_WITH_LEN("OK"));
1919
1921
case HA_ADMIN_FAILED:
1920
session->getClient()->store(STRING_WITH_LEN("status"));
1921
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1922
session->client->store(STRING_WITH_LEN("status"));
1923
session->client->store(STRING_WITH_LEN("Operation failed"));
1924
1926
case HA_ADMIN_REJECT:
1925
session->getClient()->store(STRING_WITH_LEN("status"));
1926
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1927
session->client->store(STRING_WITH_LEN("status"));
1928
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1927
1929
open_for_modify= false;
1930
1932
case HA_ADMIN_ALREADY_DONE:
1931
session->getClient()->store(STRING_WITH_LEN("status"));
1932
session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
1933
session->client->store(STRING_WITH_LEN("status"));
1934
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1935
1937
case HA_ADMIN_CORRUPT:
1936
session->getClient()->store(STRING_WITH_LEN("error"));
1937
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1938
session->client->store(STRING_WITH_LEN("error"));
1939
session->client->store(STRING_WITH_LEN("Corrupt"));
1941
1943
case HA_ADMIN_INVALID:
1942
session->getClient()->store(STRING_WITH_LEN("error"));
1943
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1944
session->client->store(STRING_WITH_LEN("error"));
1945
session->client->store(STRING_WITH_LEN("Invalid argument"));
1946
1948
default: // Probably HA_ADMIN_INTERNAL_ERROR
2001
2004
Altough exclusive name-lock on target table protects us from concurrent
2002
2005
DML and DDL operations on it we still want to wrap .FRM creation and call
2003
2006
to plugin::StorageEngine::createTable() in critical section protected by
2004
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2007
LOCK_open in order to provide minimal atomicity against operations which
2005
2008
disregard name-locks, like I_S implementation, for example. This is a
2006
2009
temporary and should not be copied. Instead we should fix our code to
2007
2010
always honor name-locks.
2009
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2012
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2010
2013
during the call to plugin::StorageEngine::createTable().
2011
2014
See bug #28614 for more info.
2013
static bool create_table_wrapper(Session &session,
2014
const message::Table& create_table_proto,
2015
identifier::Table::const_reference destination_identifier,
2016
identifier::Table::const_reference source_identifier,
2016
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2017
TableIdentifier &destination_identifier,
2018
TableIdentifier &src_table,
2017
2019
bool is_engine_set)
2019
// We require an additional table message because during parsing we used
2020
// a "new" message and it will not have all of the information that the
2021
// source table message would have.
2022
message::Table new_table_message;
2024
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2026
if (not source_table_message)
2028
my_error(ER_TABLE_UNKNOWN, source_identifier);
2032
new_table_message.CopyFrom(*source_table_message);
2021
int protoerr= EEXIST;
2022
message::Table new_proto;
2023
message::Table src_proto;
2025
protoerr= plugin::StorageEngine::getTableDefinition(session,
2028
new_proto.CopyFrom(src_proto);
2034
2030
if (destination_identifier.isTmp())
2036
new_table_message.set_type(message::Table::TEMPORARY);
2032
new_proto.set_type(message::Table::TEMPORARY);
2040
new_table_message.set_type(message::Table::STANDARD);
2036
new_proto.set_type(message::Table::STANDARD);
2043
2039
if (is_engine_set)
2045
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2041
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2048
2044
{ // We now do a selective copy of elements on to the new table.
2049
new_table_message.set_name(create_table_proto.name());
2050
new_table_message.set_schema(create_table_proto.schema());
2051
new_table_message.set_catalog(create_table_proto.catalog());
2045
new_proto.set_name(create_table_proto.name());
2046
new_proto.set_schema(create_table_proto.schema());
2047
new_proto.set_catalog(create_table_proto.catalog());
2054
/* Fix names of foreign keys being added */
2055
for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2050
if (protoerr && protoerr != EEXIST)
2057
if (new_table_message.fk_constraint(j).has_name())
2059
std::string name(new_table_message.name());
2062
name.append("_ibfk_");
2063
snprintf(number, sizeof(number), "%d", j+1);
2064
name.append(number);
2066
message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2067
pfkey->set_name(name);
2052
if (errno == ENOENT)
2053
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2055
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2072
2061
As mysql_truncate don't work on a new table at this stage of
2073
creation, instead create the table directly (for both normal and temporary tables).
2062
creation, instead create the table directly (for both normal
2063
and temporary tables).
2075
bool success= plugin::StorageEngine::createTable(session,
2076
destination_identifier,
2065
int err= plugin::StorageEngine::createTable(session,
2066
destination_identifier,
2079
if (success && not destination_identifier.isTmp())
2069
if (err == false && not destination_identifier.isTmp())
2081
2071
TransactionServices &transaction_services= TransactionServices::singleton();
2082
transaction_services.createTable(session, new_table_message);
2072
transaction_services.createTable(&session, new_proto);
2075
return err ? false : true;
2089
2079
Create a table identical to the specified table
2082
mysql_create_like_table()
2093
2083
session Thread object
2094
2084
table Table list element for target table
2095
2085
src_table Table list element for source table
2103
bool create_like_table(Session* session,
2104
identifier::Table::const_reference destination_identifier,
2105
identifier::Table::const_reference source_identifier,
2106
message::Table &create_table_proto,
2107
bool is_if_not_exists,
2093
bool mysql_create_like_table(Session* session,
2094
TableIdentifier &destination_identifier,
2095
TableList* table, TableList* src_table,
2096
message::Table &create_table_proto,
2097
bool is_if_not_exists,
2100
char *db= table->db;
2101
char *table_name= table->table_name;
2110
2102
bool res= true;
2111
bool table_exists= false;
2106
By opening source table we guarantee that it exists and no concurrent
2107
DDL operation will mess with it. Later we also take an exclusive
2108
name-lock on target table name, which makes copying of .frm cursor,
2109
call to plugin::StorageEngine::createTable() and binlogging atomic
2110
against concurrent DML and DDL operations on target table.
2111
Thus by holding both these "locks" we ensure that our statement is
2112
properly isolated from all concurrent operations which matter.
2114
if (session->open_tables_from_list(&src_table, ¬_used))
2117
TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
2118
src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
2114
2123
Check that destination tables does not exist. Note that its name
2202
2209
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2210
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2211
ER(ER_TABLE_EXISTS_ERROR), table_name);
2205
2212
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2213
ER_TABLE_EXISTS_ERROR,warn_buff);
2218
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2226
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
2228
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2230
return(mysql_admin_table(session, tables, check_opt,
2224
2231
"analyze", lock_type, true,
2225
2232
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2236
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
2238
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2240
return(mysql_admin_table(session, tables, check_opt,
2234
2241
"check", lock_type,
2236
2243
&Cursor::ha_check));