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.
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
LOCK_open.lock(); /* 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))
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
TableIdentifier identifier(db, table->table_name);
225
abort_locked_tables(session, identifier);
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, identifier)))
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
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;
1846
1866
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1867
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"));
1868
session->client->store(table_name);
1869
session->client->store(operator_name);
1870
session->client->store(STRING_WITH_LEN("error"));
1851
1871
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);
1873
session->client->store(buff, length);
1874
transaction_services.autocommitOrRollback(session, false);
1855
1875
session->endTransaction(COMMIT);
1856
1876
session->close_thread_tables();
1857
session->getLex()->reset_query_tables_list(false);
1877
lex->reset_query_tables_list(false);
1858
1878
table->table=0; // For query cache
1859
if (session->getClient()->flush())
1879
if (session->client->flush())
1864
1884
/* Close all instances of the table to allow repair to rename files */
1865
1885
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);
1887
LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1888
const char *old_message=session->enter_cond(COND_refresh.native_handle(), LOCK_open.native_handle(),
1889
"Waiting to get writelock");
1890
mysql_lock_abort(session,table->table);
1891
TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
1892
remove_table_from_cache(session, identifier,
1893
RTFC_WAIT_OTHER_THREAD_FLAG |
1894
RTFC_CHECK_KILLED_FLAG);
1873
1895
session->exit_cond(old_message);
1874
if (session->getKilled())
1896
if (session->killed)
1876
1898
open_for_modify= 0;
1883
session->getLex()->cleanup_after_one_table_open();
1905
lex->cleanup_after_one_table_open();
1884
1906
session->clear_error(); // these errors shouldn't get client
1886
List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1908
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1909
DRIZZLE_ERROR *err;
1888
1910
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,
1912
session->client->store(table_name);
1913
session->client->store(operator_name);
1914
session->client->store(warning_level_names[err->level].str,
1893
1915
warning_level_names[err->level].length);
1894
session->getClient()->store(err->msg);
1895
if (session->getClient()->flush())
1916
session->client->store(err->msg);
1917
if (session->client->flush())
1898
1920
drizzle_reset_errors(session, true);
1900
session->getClient()->store(table_name.c_str());
1901
session->getClient()->store(operator_name);
1922
session->client->store(table_name);
1923
session->client->store(operator_name);
1903
1925
switch (result_code) {
1904
1926
case HA_ADMIN_NOT_IMPLEMENTED:
1906
1928
char buf[ERRMSGSIZE+20];
1907
1929
uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1930
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
session->getClient()->store(STRING_WITH_LEN("note"));
1910
session->getClient()->store(buf, length);
1931
session->client->store(STRING_WITH_LEN("note"));
1932
session->client->store(buf, length);
1914
1936
case HA_ADMIN_OK:
1915
session->getClient()->store(STRING_WITH_LEN("status"));
1916
session->getClient()->store(STRING_WITH_LEN("OK"));
1937
session->client->store(STRING_WITH_LEN("status"));
1938
session->client->store(STRING_WITH_LEN("OK"));
1919
1941
case HA_ADMIN_FAILED:
1920
session->getClient()->store(STRING_WITH_LEN("status"));
1921
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1942
session->client->store(STRING_WITH_LEN("status"));
1943
session->client->store(STRING_WITH_LEN("Operation failed"));
1924
1946
case HA_ADMIN_REJECT:
1925
session->getClient()->store(STRING_WITH_LEN("status"));
1926
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1947
session->client->store(STRING_WITH_LEN("status"));
1948
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1927
1949
open_for_modify= false;
1930
1952
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"));
1953
session->client->store(STRING_WITH_LEN("status"));
1954
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1935
1957
case HA_ADMIN_CORRUPT:
1936
session->getClient()->store(STRING_WITH_LEN("error"));
1937
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1958
session->client->store(STRING_WITH_LEN("error"));
1959
session->client->store(STRING_WITH_LEN("Corrupt"));
1941
1963
case HA_ADMIN_INVALID:
1942
session->getClient()->store(STRING_WITH_LEN("error"));
1943
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1964
session->client->store(STRING_WITH_LEN("error"));
1965
session->client->store(STRING_WITH_LEN("Invalid argument"));
1946
1968
default: // Probably HA_ADMIN_INTERNAL_ERROR
2001
2024
Altough exclusive name-lock on target table protects us from concurrent
2002
2025
DML and DDL operations on it we still want to wrap .FRM creation and call
2003
2026
to plugin::StorageEngine::createTable() in critical section protected by
2004
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2027
LOCK_open in order to provide minimal atomicity against operations which
2005
2028
disregard name-locks, like I_S implementation, for example. This is a
2006
2029
temporary and should not be copied. Instead we should fix our code to
2007
2030
always honor name-locks.
2009
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2032
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2010
2033
during the call to plugin::StorageEngine::createTable().
2011
2034
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,
2036
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2037
TableIdentifier &destination_identifier,
2038
TableIdentifier &src_table,
2017
2039
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);
2041
int protoerr= EEXIST;
2042
message::Table new_proto;
2043
message::Table src_proto;
2045
protoerr= plugin::StorageEngine::getTableDefinition(session,
2048
new_proto.CopyFrom(src_proto);
2034
2050
if (destination_identifier.isTmp())
2036
new_table_message.set_type(message::Table::TEMPORARY);
2052
new_proto.set_type(message::Table::TEMPORARY);
2040
new_table_message.set_type(message::Table::STANDARD);
2056
new_proto.set_type(message::Table::STANDARD);
2043
2059
if (is_engine_set)
2045
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2061
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2048
2064
{ // 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());
2065
new_proto.set_name(create_table_proto.name());
2066
new_proto.set_schema(create_table_proto.schema());
2067
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++)
2070
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);
2072
if (errno == ENOENT)
2073
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2075
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2072
2081
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).
2082
creation, instead create the table directly (for both normal
2083
and temporary tables).
2075
bool success= plugin::StorageEngine::createTable(session,
2076
destination_identifier,
2085
int err= plugin::StorageEngine::createTable(session,
2086
destination_identifier,
2079
if (success && not destination_identifier.isTmp())
2089
if (err == false && not destination_identifier.isTmp())
2081
2091
TransactionServices &transaction_services= TransactionServices::singleton();
2082
transaction_services.createTable(session, new_table_message);
2092
transaction_services.createTable(&session, new_proto);
2095
return err ? false : true;
2089
2099
Create a table identical to the specified table
2102
mysql_create_like_table()
2093
2103
session Thread object
2094
2104
table Table list element for target table
2095
2105
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,
2113
bool mysql_create_like_table(Session* session,
2114
TableIdentifier &destination_identifier,
2115
TableList* table, TableList* src_table,
2116
message::Table &create_table_proto,
2117
bool is_if_not_exists,
2120
char *db= table->db;
2121
char *table_name= table->table_name;
2110
2122
bool res= true;
2111
bool table_exists= false;
2126
By opening source table we guarantee that it exists and no concurrent
2127
DDL operation will mess with it. Later we also take an exclusive
2128
name-lock on target table name, which makes copying of .frm cursor,
2129
call to plugin::StorageEngine::createTable() and binlogging atomic
2130
against concurrent DML and DDL operations on target table.
2131
Thus by holding both these "locks" we ensure that our statement is
2132
properly isolated from all concurrent operations which matter.
2134
if (session->open_tables_from_list(&src_table, ¬_used))
2137
TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
2138
src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
2114
2143
Check that destination tables does not exist. Note that its name
2202
2229
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2230
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2231
ER(ER_TABLE_EXISTS_ERROR), table_name);
2205
2232
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2233
ER_TABLE_EXISTS_ERROR,warn_buff);
2238
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2246
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
2248
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2250
return(mysql_admin_table(session, tables, check_opt,
2224
2251
"analyze", lock_type, true,
2225
2252
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2256
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
2258
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2260
return(mysql_admin_table(session, tables, check_opt,
2234
2261
"check", lock_type,
2236
2263
&Cursor::ha_check));