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>
138
139
-1 Thread was killed
141
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
144
145
TableList *table;
145
util::string::vector wrong_tables;
147
148
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
150
LOCK_open.lock(); /* Part 2 of rm a table */
153
If we have the table in the definition cache, we don't have to check the
154
.frm cursor to find if the table is a normal table (not view) and what
158
for (table= tables; table; table= table->next_local)
160
TableIdentifier identifier(table->db, table->table_name);
162
table->setDbType(NULL);
164
if ((share= TableShare::getShare(identifier)))
166
table->setDbType(share->db_type());
170
if (not drop_temporary && lock_table_names_exclusively(session, tables))
176
/* Don't give warnings for not found errors, as we already generate notes */
177
session->no_warnings_for_error= 1;
179
for (table= tables; table; table= table->next_local)
183
error= session->drop_temporary_table(table);
187
// removed temporary table
191
goto err_with_placeholders;
193
// temporary table not found
197
if (drop_temporary == false)
200
TableIdentifier identifier(db, table->table_name);
201
abort_locked_tables(session, identifier);
202
remove_table_from_cache(session, identifier,
203
RTFC_WAIT_OTHER_THREAD_FLAG |
204
RTFC_CHECK_KILLED_FLAG);
206
If the table was used in lock tables, remember it so that
207
unlock_table_names can free it
209
if ((locked_table= drop_locked_tables(session, identifier)))
210
table->table= locked_table;
215
goto err_with_placeholders;
218
TableIdentifier identifier(db, table->table_name, table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
220
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
222
// Table was not found on disk and table can't be created from engine
224
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
225
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
175
// temporary table not found
232
error= plugin::StorageEngine::dropTable(*session, identifier);
234
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())
237
session->clear_error();
240
if (error == HA_ERR_ROW_IS_REFERENCED)
242
/* the table is referenced by a foreign key constraint */
243
foreign_key_error= true;
247
if (error == 0 || (if_exists && foreign_key_error == false))
249
TransactionServices &transaction_services= TransactionServices::singleton();
250
transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
255
if (wrong_tables.length())
256
wrong_tables.append(',');
257
wrong_tables.append(String(table->table_name,system_charset_info));
261
It's safe to unlock LOCK_open: we have an exclusive lock
267
if (wrong_tables.length())
259
269
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
271
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
table_error.c_str());
272
wrong_tables.c_ptr());
515
541
else if (sql_field->unireg_check != Field::NONE)
517
542
(*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)
553
static int mysql_prepare_create_table(Session *session,
554
HA_CREATE_INFO *create_info,
555
message::Table &create_proto,
556
AlterInfo *alter_info,
558
uint32_t *db_options,
559
KeyInfo **key_info_buffer,
561
int select_field_count)
551
563
const char *key_name;
552
564
CreateField *sql_field,*dup_field;
1846
1828
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1829
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"));
1830
session->client->store(table_name);
1831
session->client->store(operator_name);
1832
session->client->store(STRING_WITH_LEN("error"));
1851
1833
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);
1835
session->client->store(buff, length);
1836
transaction_services.autocommitOrRollback(session, false);
1855
1837
session->endTransaction(COMMIT);
1856
1838
session->close_thread_tables();
1857
session->getLex()->reset_query_tables_list(false);
1839
lex->reset_query_tables_list(false);
1858
1840
table->table=0; // For query cache
1859
if (session->getClient()->flush())
1841
if (session->client->flush())
1864
1846
/* Close all instances of the table to allow repair to rename files */
1865
1847
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(),
1849
LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1850
const char *old_message=session->enter_cond(COND_refresh, LOCK_open,
1869
1851
"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);
1852
mysql_lock_abort(session,table->table);
1853
TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
1854
remove_table_from_cache(session, identifier,
1855
RTFC_WAIT_OTHER_THREAD_FLAG |
1856
RTFC_CHECK_KILLED_FLAG);
1873
1857
session->exit_cond(old_message);
1874
if (session->getKilled())
1858
if (session->killed)
1876
1860
open_for_modify= 0;
1883
session->getLex()->cleanup_after_one_table_open();
1867
lex->cleanup_after_one_table_open();
1884
1868
session->clear_error(); // these errors shouldn't get client
1886
List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1870
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1871
DRIZZLE_ERROR *err;
1888
1872
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,
1874
session->client->store(table_name);
1875
session->client->store(operator_name);
1876
session->client->store(warning_level_names[err->level].str,
1893
1877
warning_level_names[err->level].length);
1894
session->getClient()->store(err->msg);
1895
if (session->getClient()->flush())
1878
session->client->store(err->msg);
1879
if (session->client->flush())
1898
1882
drizzle_reset_errors(session, true);
1900
session->getClient()->store(table_name.c_str());
1901
session->getClient()->store(operator_name);
1884
session->client->store(table_name);
1885
session->client->store(operator_name);
1903
1887
switch (result_code) {
1904
1888
case HA_ADMIN_NOT_IMPLEMENTED:
1906
1890
char buf[ERRMSGSIZE+20];
1907
1891
uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1892
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
session->getClient()->store(STRING_WITH_LEN("note"));
1910
session->getClient()->store(buf, length);
1893
session->client->store(STRING_WITH_LEN("note"));
1894
session->client->store(buf, length);
1914
1898
case HA_ADMIN_OK:
1915
session->getClient()->store(STRING_WITH_LEN("status"));
1916
session->getClient()->store(STRING_WITH_LEN("OK"));
1899
session->client->store(STRING_WITH_LEN("status"));
1900
session->client->store(STRING_WITH_LEN("OK"));
1919
1903
case HA_ADMIN_FAILED:
1920
session->getClient()->store(STRING_WITH_LEN("status"));
1921
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1904
session->client->store(STRING_WITH_LEN("status"));
1905
session->client->store(STRING_WITH_LEN("Operation failed"));
1924
1908
case HA_ADMIN_REJECT:
1925
session->getClient()->store(STRING_WITH_LEN("status"));
1926
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1909
session->client->store(STRING_WITH_LEN("status"));
1910
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1927
1911
open_for_modify= false;
1930
1914
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"));
1915
session->client->store(STRING_WITH_LEN("status"));
1916
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1935
1919
case HA_ADMIN_CORRUPT:
1936
session->getClient()->store(STRING_WITH_LEN("error"));
1937
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1920
session->client->store(STRING_WITH_LEN("error"));
1921
session->client->store(STRING_WITH_LEN("Corrupt"));
1941
1925
case HA_ADMIN_INVALID:
1942
session->getClient()->store(STRING_WITH_LEN("error"));
1943
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1926
session->client->store(STRING_WITH_LEN("error"));
1927
session->client->store(STRING_WITH_LEN("Invalid argument"));
1946
1930
default: // Probably HA_ADMIN_INTERNAL_ERROR
2001
1985
Altough exclusive name-lock on target table protects us from concurrent
2002
1986
DML and DDL operations on it we still want to wrap .FRM creation and call
2003
1987
to plugin::StorageEngine::createTable() in critical section protected by
2004
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1988
LOCK_open in order to provide minimal atomicity against operations which
2005
1989
disregard name-locks, like I_S implementation, for example. This is a
2006
1990
temporary and should not be copied. Instead we should fix our code to
2007
1991
always honor name-locks.
2009
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1993
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2010
1994
during the call to plugin::StorageEngine::createTable().
2011
1995
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,
1997
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1998
TableIdentifier &destination_identifier,
1999
TableIdentifier &src_table,
2017
2000
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);
2002
int protoerr= EEXIST;
2003
message::Table new_proto;
2004
message::Table src_proto;
2006
protoerr= plugin::StorageEngine::getTableDefinition(session,
2009
new_proto.CopyFrom(src_proto);
2034
2011
if (destination_identifier.isTmp())
2036
new_table_message.set_type(message::Table::TEMPORARY);
2013
new_proto.set_type(message::Table::TEMPORARY);
2040
new_table_message.set_type(message::Table::STANDARD);
2017
new_proto.set_type(message::Table::STANDARD);
2043
2020
if (is_engine_set)
2045
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2022
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2048
2025
{ // 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());
2026
new_proto.set_name(create_table_proto.name());
2027
new_proto.set_schema(create_table_proto.schema());
2028
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++)
2031
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);
2033
if (errno == ENOENT)
2034
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2036
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2072
2042
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).
2043
creation, instead create the table directly (for both normal
2044
and temporary tables).
2075
bool success= plugin::StorageEngine::createTable(session,
2076
destination_identifier,
2046
int err= plugin::StorageEngine::createTable(session,
2047
destination_identifier,
2079
if (success && not destination_identifier.isTmp())
2050
if (err == false && not destination_identifier.isTmp())
2081
2052
TransactionServices &transaction_services= TransactionServices::singleton();
2082
transaction_services.createTable(session, new_table_message);
2053
transaction_services.createTable(&session, new_proto);
2056
return err ? false : true;
2089
2060
Create a table identical to the specified table
2063
mysql_create_like_table()
2093
2064
session Thread object
2094
2065
table Table list element for target table
2095
2066
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,
2074
bool mysql_create_like_table(Session* session,
2075
TableIdentifier &destination_identifier,
2076
TableList* table, TableList* src_table,
2077
message::Table &create_table_proto,
2078
bool is_if_not_exists,
2081
char *db= table->db;
2082
char *table_name= table->table_name;
2110
2083
bool res= true;
2111
bool table_exists= false;
2087
By opening source table we guarantee that it exists and no concurrent
2088
DDL operation will mess with it. Later we also take an exclusive
2089
name-lock on target table name, which makes copying of .frm cursor,
2090
call to plugin::StorageEngine::createTable() and binlogging atomic
2091
against concurrent DML and DDL operations on target table.
2092
Thus by holding both these "locks" we ensure that our statement is
2093
properly isolated from all concurrent operations which matter.
2095
if (session->open_tables_from_list(&src_table, ¬_used))
2098
TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
2099
src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
2114
2104
Check that destination tables does not exist. Note that its name
2202
2190
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2191
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2192
ER(ER_TABLE_EXISTS_ERROR), table_name);
2205
2193
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2194
ER_TABLE_EXISTS_ERROR,warn_buff);
2199
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2207
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
2209
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2211
return(mysql_admin_table(session, tables, check_opt,
2224
2212
"analyze", lock_type, true,
2225
2213
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2217
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
2219
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2221
return(mysql_admin_table(session, tables, check_opt,
2234
2222
"check", lock_type,
2236
2224
&Cursor::ha_check));