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"
30
#include <drizzled/db.h>
29
31
#include <drizzled/lock.h>
30
32
#include <drizzled/unireg.h>
31
33
#include <drizzled/item/int.h>
32
34
#include <drizzled/item/empty_string.h>
33
35
#include <drizzled/transaction_services.h>
34
#include <drizzled/transaction_services.h>
36
#include "drizzled/transaction_services.h"
35
37
#include <drizzled/table_proto.h>
36
38
#include <drizzled/plugin/client.h>
37
39
#include <drizzled/identifier.h>
38
#include <drizzled/internal/m_string.h>
39
#include <drizzled/global_charset_info.h>
40
#include <drizzled/charset.h>
42
#include <drizzled/definition/cache.h>
44
#include <drizzled/statement/alter_table.h>
45
#include <drizzled/sql_table.h>
46
#include <drizzled/pthread_globals.h>
47
#include <drizzled/typelib.h>
48
#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"
50
49
#include <algorithm>
137
139
-1 Thread was killed
140
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
145
TableList *table;
144
util::string::vector wrong_tables;
146
148
bool foreign_key_error= false;
150
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
152
if (not drop_temporary && session->lock_table_names_exclusively(tables))
157
/* Don't give warnings for not found errors, as we already generate notes */
158
session->no_warnings_for_error= 1;
160
for (table= tables; table; table= table->next_local)
162
identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
164
error= session->drop_temporary_table(tmp_identifier);
168
// 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),
174
// temporary table not found
232
error= plugin::StorageEngine::dropTable(*session, identifier);
234
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
178
if (drop_temporary == false)
181
abort_locked_tables(session, tmp_identifier);
182
table::Cache::singleton().removeTable(session, tmp_identifier,
183
RTFC_WAIT_OTHER_THREAD_FLAG |
184
RTFC_CHECK_KILLED_FLAG);
186
If the table was used in lock tables, remember it so that
187
unlock_table_names can free it
189
if ((locked_table= drop_locked_tables(session, tmp_identifier)))
190
table->table= locked_table;
192
if (session->getKilled())
198
identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
200
message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
202
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
// 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());
218
drizzled::error_t local_error;
220
/* Generate transaction event ONLY when we successfully drop */
221
if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
223
if (message) // If we have no definition, we don't know if the table should have been replicated
225
TransactionServices &transaction_services= TransactionServices::singleton();
226
transaction_services.dropTable(*session, identifier, *message, if_exists);
231
if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
234
session->clear_error();
237
if (local_error == HA_ERR_ROW_IS_REFERENCED)
239
/* the table is referenced by a foreign key constraint */
240
foreign_key_error= true;
248
wrong_tables.push_back(table->getTableName());
252
tables->unlock_table_names();
256
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())
258
269
if (not foreign_key_error)
260
std::string table_error;
262
for (util::string::vector::iterator iter= wrong_tables.begin();
263
iter != wrong_tables.end();
269
table_error.resize(table_error.size() -1);
271
271
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
272
table_error.c_str());
272
wrong_tables.c_ptr());
514
541
else if (sql_field->unireg_check != Field::NONE)
516
542
(*timestamps_with_niladic)++;
523
case DRIZZLE_TYPE_BOOLEAN:
524
case DRIZZLE_TYPE_DATE: // Rest of string types
525
case DRIZZLE_TYPE_DATETIME:
526
case DRIZZLE_TYPE_DECIMAL:
527
case DRIZZLE_TYPE_DOUBLE:
528
case DRIZZLE_TYPE_LONG:
529
case DRIZZLE_TYPE_LONGLONG:
530
case DRIZZLE_TYPE_NULL:
531
case DRIZZLE_TYPE_TIME:
532
case DRIZZLE_TYPE_UUID:
533
case DRIZZLE_TYPE_VARCHAR:
540
static int prepare_create_table(Session *session,
541
HA_CREATE_INFO *create_info,
542
message::Table &create_proto,
543
AlterInfo *alter_info,
545
uint32_t *db_options,
546
KeyInfo **key_info_buffer,
548
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)
550
563
const char *key_name;
551
564
CreateField *sql_field,*dup_field;
1845
1827
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1846
1828
uint32_t length;
1847
session->getClient()->store(table_name.c_str());
1848
session->getClient()->store(operator_name);
1849
session->getClient()->store(STRING_WITH_LEN("error"));
1829
session->client->store(table_name);
1830
session->client->store(operator_name);
1831
session->client->store(STRING_WITH_LEN("error"));
1850
1832
length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1851
table_name.c_str());
1852
session->getClient()->store(buff, length);
1853
transaction_services.autocommitOrRollback(*session, false);
1834
session->client->store(buff, length);
1835
transaction_services.autocommitOrRollback(session, false);
1854
1836
session->endTransaction(COMMIT);
1855
1837
session->close_thread_tables();
1856
session->getLex()->reset_query_tables_list(false);
1838
lex->reset_query_tables_list(false);
1857
1839
table->table=0; // For query cache
1858
if (session->getClient()->flush())
1840
if (session->client->flush())
1863
1845
/* Close all instances of the table to allow repair to rename files */
1864
1846
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1866
table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1867
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1848
LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1849
const char *old_message=session->enter_cond(COND_refresh, LOCK_open,
1868
1850
"Waiting to get writelock");
1869
session->abortLock(table->table);
1870
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1871
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1851
mysql_lock_abort(session,table->table);
1852
TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
1853
remove_table_from_cache(session, identifier,
1854
RTFC_WAIT_OTHER_THREAD_FLAG |
1855
RTFC_CHECK_KILLED_FLAG);
1872
1856
session->exit_cond(old_message);
1873
if (session->getKilled())
1857
if (session->killed)
1875
1859
open_for_modify= 0;
1882
session->getLex()->cleanup_after_one_table_open();
1866
lex->cleanup_after_one_table_open();
1883
1867
session->clear_error(); // these errors shouldn't get client
1885
List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1869
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1886
1870
DRIZZLE_ERROR *err;
1887
1871
while ((err= it++))
1889
session->getClient()->store(table_name.c_str());
1890
session->getClient()->store(operator_name);
1891
session->getClient()->store(warning_level_names[err->level].str,
1873
session->client->store(table_name);
1874
session->client->store(operator_name);
1875
session->client->store(warning_level_names[err->level].str,
1892
1876
warning_level_names[err->level].length);
1893
session->getClient()->store(err->msg);
1894
if (session->getClient()->flush())
1877
session->client->store(err->msg);
1878
if (session->client->flush())
1897
1881
drizzle_reset_errors(session, true);
1899
session->getClient()->store(table_name.c_str());
1900
session->getClient()->store(operator_name);
1883
session->client->store(table_name);
1884
session->client->store(operator_name);
1902
1886
switch (result_code) {
1903
1887
case HA_ADMIN_NOT_IMPLEMENTED:
1905
1889
char buf[ERRMSGSIZE+20];
1906
1890
uint32_t length=snprintf(buf, ERRMSGSIZE,
1907
1891
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1908
session->getClient()->store(STRING_WITH_LEN("note"));
1909
session->getClient()->store(buf, length);
1892
session->client->store(STRING_WITH_LEN("note"));
1893
session->client->store(buf, length);
1913
1897
case HA_ADMIN_OK:
1914
session->getClient()->store(STRING_WITH_LEN("status"));
1915
session->getClient()->store(STRING_WITH_LEN("OK"));
1898
session->client->store(STRING_WITH_LEN("status"));
1899
session->client->store(STRING_WITH_LEN("OK"));
1918
1902
case HA_ADMIN_FAILED:
1919
session->getClient()->store(STRING_WITH_LEN("status"));
1920
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1903
session->client->store(STRING_WITH_LEN("status"));
1904
session->client->store(STRING_WITH_LEN("Operation failed"));
1923
1907
case HA_ADMIN_REJECT:
1924
session->getClient()->store(STRING_WITH_LEN("status"));
1925
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1908
session->client->store(STRING_WITH_LEN("status"));
1909
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1926
1910
open_for_modify= false;
1929
1913
case HA_ADMIN_ALREADY_DONE:
1930
session->getClient()->store(STRING_WITH_LEN("status"));
1931
session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
1914
session->client->store(STRING_WITH_LEN("status"));
1915
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1934
1918
case HA_ADMIN_CORRUPT:
1935
session->getClient()->store(STRING_WITH_LEN("error"));
1936
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1919
session->client->store(STRING_WITH_LEN("error"));
1920
session->client->store(STRING_WITH_LEN("Corrupt"));
1940
1924
case HA_ADMIN_INVALID:
1941
session->getClient()->store(STRING_WITH_LEN("error"));
1942
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1925
session->client->store(STRING_WITH_LEN("error"));
1926
session->client->store(STRING_WITH_LEN("Invalid argument"));
1945
1929
default: // Probably HA_ADMIN_INTERNAL_ERROR
2000
1984
Altough exclusive name-lock on target table protects us from concurrent
2001
1985
DML and DDL operations on it we still want to wrap .FRM creation and call
2002
1986
to plugin::StorageEngine::createTable() in critical section protected by
2003
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1987
LOCK_open in order to provide minimal atomicity against operations which
2004
1988
disregard name-locks, like I_S implementation, for example. This is a
2005
1989
temporary and should not be copied. Instead we should fix our code to
2006
1990
always honor name-locks.
2008
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1992
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2009
1993
during the call to plugin::StorageEngine::createTable().
2010
1994
See bug #28614 for more info.
2012
static bool create_table_wrapper(Session &session,
2013
const message::Table& create_table_proto,
2014
identifier::Table::const_reference destination_identifier,
2015
identifier::Table::const_reference source_identifier,
1996
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1997
TableIdentifier &destination_identifier,
1998
TableIdentifier &src_table,
2016
1999
bool is_engine_set)
2018
// We require an additional table message because during parsing we used
2019
// a "new" message and it will not have all of the information that the
2020
// source table message would have.
2021
message::Table new_table_message;
2023
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2025
if (not source_table_message)
2027
my_error(ER_TABLE_UNKNOWN, source_identifier);
2031
new_table_message.CopyFrom(*source_table_message);
2001
int protoerr= EEXIST;
2002
message::Table new_proto;
2003
message::Table src_proto;
2005
protoerr= plugin::StorageEngine::getTableDefinition(session,
2008
new_proto.CopyFrom(src_proto);
2033
2010
if (destination_identifier.isTmp())
2035
new_table_message.set_type(message::Table::TEMPORARY);
2012
new_proto.set_type(message::Table::TEMPORARY);
2039
new_table_message.set_type(message::Table::STANDARD);
2016
new_proto.set_type(message::Table::STANDARD);
2042
2019
if (is_engine_set)
2044
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2021
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2047
2024
{ // We now do a selective copy of elements on to the new table.
2048
new_table_message.set_name(create_table_proto.name());
2049
new_table_message.set_schema(create_table_proto.schema());
2050
new_table_message.set_catalog(create_table_proto.catalog());
2025
new_proto.set_name(create_table_proto.name());
2026
new_proto.set_schema(create_table_proto.schema());
2027
new_proto.set_catalog(create_table_proto.catalog());
2053
/* Fix names of foreign keys being added */
2054
for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2030
if (protoerr && protoerr != EEXIST)
2056
if (new_table_message.fk_constraint(j).has_name())
2058
std::string name(new_table_message.name());
2061
name.append("_ibfk_");
2062
snprintf(number, sizeof(number), "%d", j+1);
2063
name.append(number);
2065
message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2066
pfkey->set_name(name);
2032
if (errno == ENOENT)
2033
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2035
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2071
2041
As mysql_truncate don't work on a new table at this stage of
2072
creation, instead create the table directly (for both normal and temporary tables).
2042
creation, instead create the table directly (for both normal
2043
and temporary tables).
2074
bool success= plugin::StorageEngine::createTable(session,
2075
destination_identifier,
2045
int err= plugin::StorageEngine::createTable(session,
2046
destination_identifier,
2078
if (success && not destination_identifier.isTmp())
2049
if (err == false && not destination_identifier.isTmp())
2080
2051
TransactionServices &transaction_services= TransactionServices::singleton();
2081
transaction_services.createTable(session, new_table_message);
2052
transaction_services.createTable(&session, new_proto);
2055
return err ? false : true;
2088
2059
Create a table identical to the specified table
2062
mysql_create_like_table()
2092
2063
session Thread object
2093
2064
table Table list element for target table
2094
2065
src_table Table list element for source table
2102
bool create_like_table(Session* session,
2103
identifier::Table::const_reference destination_identifier,
2104
identifier::Table::const_reference source_identifier,
2105
message::Table &create_table_proto,
2106
bool is_if_not_exists,
2073
bool mysql_create_like_table(Session* session,
2074
TableIdentifier &destination_identifier,
2075
TableList* table, TableList* src_table,
2076
message::Table &create_table_proto,
2077
bool is_if_not_exists,
2080
char *db= table->db;
2081
char *table_name= table->table_name;
2109
2082
bool res= true;
2110
bool table_exists= false;
2086
By opening source table we guarantee that it exists and no concurrent
2087
DDL operation will mess with it. Later we also take an exclusive
2088
name-lock on target table name, which makes copying of .frm cursor,
2089
call to plugin::StorageEngine::createTable() and binlogging atomic
2090
against concurrent DML and DDL operations on target table.
2091
Thus by holding both these "locks" we ensure that our statement is
2092
properly isolated from all concurrent operations which matter.
2094
if (session->open_tables_from_list(&src_table, ¬_used))
2097
TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
2098
src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
2113
2103
Check that destination tables does not exist. Note that its name
2201
2189
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2202
2190
snprintf(warn_buff, sizeof(warn_buff),
2203
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2191
ER(ER_TABLE_EXISTS_ERROR), table_name);
2204
2192
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2205
ER_TABLE_EXISTS_ERROR, warn_buff);
2209
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2193
ER_TABLE_EXISTS_ERROR,warn_buff);
2198
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2218
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2206
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2220
2208
thr_lock_type lock_type = TL_READ_NO_INSERT;
2222
return(admin_table(session, tables, check_opt,
2210
return(mysql_admin_table(session, tables, check_opt,
2223
2211
"analyze", lock_type, true,
2224
2212
&Cursor::ha_analyze));
2228
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2216
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2230
2218
thr_lock_type lock_type = TL_READ_NO_INSERT;
2232
return(admin_table(session, tables, check_opt,
2220
return(mysql_admin_table(session, tables, check_opt,
2233
2221
"check", lock_type,
2235
2223
&Cursor::ha_check));