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"
44
#include "drizzled/definition/cache.h"
47
#include "drizzled/statement/alter_table.h"
48
#include "drizzled/sql_table.h"
49
#include "drizzled/pthread_globals.h"
51
51
#include <algorithm>
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);
201
TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
203
203
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
205
205
// Table was not found on disk and table can't be created from engine
208
207
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
208
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
209
table->getTableName());
221
219
/* Generate transaction event ONLY when we successfully drop */
222
220
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);
222
TransactionServices &transaction_services= TransactionServices::singleton();
223
transaction_services.dropTable(session, identifier, if_exists);
557
543
int timestamps= 0, timestamps_with_niladic= 0;
559
545
int select_field_pos,auto_increment=0;
560
List<CreateField>::iterator it(alter_info->create_list.begin());
561
List<CreateField>::iterator it2(alter_info->create_list.begin());
546
List_iterator<CreateField> it(alter_info->create_list);
547
List_iterator<CreateField> it2(alter_info->create_list);
562
548
uint32_t total_uneven_bit_length= 0;
564
550
plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
701
687
else /* not NULL */
703
689
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
704
if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
690
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
706
692
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
993
979
message::Table::Field *protofield= NULL;
995
List<Key_part_spec>::iterator cols(key->columns.begin());
996
List<Key_part_spec>::iterator cols2(key->columns.begin());
981
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
997
982
for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
1000
985
Key_part_spec *dup_column;
1001
986
int proto_field_nr= 0;
1003
it= alter_info->create_list.begin();
1005
990
while ((sql_field=it++) && ++proto_field_nr &&
1006
991
my_strcasecmp(system_charset_info,
1470
1459
/* Build a Table object to pass down to the engine, and the do the actual create. */
1471
1460
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1474
&key_info_buffer, &key_count,
1475
select_field_count))
1463
&key_info_buffer, &key_count,
1464
select_field_count))
1477
1466
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1478
1467
error= locked_create_event(session,
1495
1484
@note the following two methods implement create [temporary] table.
1497
1486
static bool drizzle_create_table(Session *session,
1498
const identifier::Table &identifier,
1487
const TableIdentifier &identifier,
1499
1488
HA_CREATE_INFO *create_info,
1500
1489
message::Table &table_proto,
1501
1490
AlterInfo *alter_info,
1552
1543
Database locking aware wrapper for create_table_no_lock(),
1554
1545
bool create_table(Session *session,
1555
const identifier::Table &identifier,
1546
const TableIdentifier &identifier,
1556
1547
HA_CREATE_INFO *create_info,
1557
1548
message::Table &table_proto,
1558
1549
AlterInfo *alter_info,
1715
1706
session->abortLock(table); /* end threads waiting on lock */
1717
1708
/* Wait until all there are no other threads that has this table open */
1718
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1709
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1719
1710
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1794
1785
for (table= tables; table; table= table->next_local)
1796
identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
std::string table_name;
1787
char table_name[NAME_LEN*2+2];
1798
1788
bool fatal_error=0;
1800
table_identifier.getSQLPath(table_name);
1790
snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
1802
1791
table->lock_type= lock_type;
1803
1792
/* open only one table from local list of command */
1813
1802
so it have to be prepared.
1814
1803
@todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1816
session->getLex()->query_tables= table;
1817
session->getLex()->query_tables_last= &table->next_global;
1818
session->getLex()->query_tables_own_last= 0;
1805
lex->query_tables= table;
1806
lex->query_tables_last= &table->next_global;
1807
lex->query_tables_own_last= 0;
1819
1808
session->no_warnings_for_error= 0;
1821
1810
session->openTablesLock(table);
1846
1835
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1836
uint32_t length;
1848
session->getClient()->store(table_name.c_str());
1837
session->getClient()->store(table_name);
1849
1838
session->getClient()->store(operator_name);
1850
1839
session->getClient()->store(STRING_WITH_LEN("error"));
1851
1840
length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
table_name.c_str());
1853
1842
session->getClient()->store(buff, length);
1854
transaction_services.autocommitOrRollback(*session, false);
1843
transaction_services.autocommitOrRollback(session, false);
1855
1844
session->endTransaction(COMMIT);
1856
1845
session->close_thread_tables();
1857
session->getLex()->reset_query_tables_list(false);
1846
lex->reset_query_tables_list(false);
1858
1847
table->table=0; // For query cache
1859
1848
if (session->getClient()->flush())
1868
1857
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1869
1858
"Waiting to get writelock");
1870
1859
session->abortLock(table->table);
1871
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1860
TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
1861
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1873
1862
session->exit_cond(old_message);
1874
1863
if (session->getKilled())
1883
session->getLex()->cleanup_after_one_table_open();
1872
lex->cleanup_after_one_table_open();
1884
1873
session->clear_error(); // these errors shouldn't get client
1886
List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1875
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1876
DRIZZLE_ERROR *err;
1888
1877
while ((err= it++))
1890
session->getClient()->store(table_name.c_str());
1879
session->getClient()->store(table_name);
1891
1880
session->getClient()->store(operator_name);
1892
1881
session->getClient()->store(warning_level_names[err->level].str,
1893
1882
warning_level_names[err->level].length);
1972
1961
boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1962
TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
1963
table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1978
transaction_services.autocommitOrRollback(*session, false);
1967
transaction_services.autocommitOrRollback(session, false);
1979
1968
session->endTransaction(COMMIT);
1980
1969
session->close_thread_tables();
1981
1970
table->table=0; // For query cache
2010
1999
during the call to plugin::StorageEngine::createTable().
2011
2000
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,
2002
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2003
const TableIdentifier &destination_identifier,
2004
const TableIdentifier &src_table,
2017
2005
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);
2008
message::Table new_proto;
2009
message::table::shared_ptr src_proto;
2011
protoerr= plugin::StorageEngine::getTableDefinition(session,
2014
new_proto.CopyFrom(*src_proto);
2034
2016
if (destination_identifier.isTmp())
2036
new_table_message.set_type(message::Table::TEMPORARY);
2018
new_proto.set_type(message::Table::TEMPORARY);
2040
new_table_message.set_type(message::Table::STANDARD);
2022
new_proto.set_type(message::Table::STANDARD);
2043
2025
if (is_engine_set)
2045
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2027
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2048
2030
{ // 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());
2031
new_proto.set_name(create_table_proto.name());
2032
new_proto.set_schema(create_table_proto.schema());
2033
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++)
2036
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);
2038
if (errno == ENOENT)
2039
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2041
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2103
2078
bool create_like_table(Session* session,
2104
identifier::Table::const_reference destination_identifier,
2105
identifier::Table::const_reference source_identifier,
2079
const TableIdentifier &destination_identifier,
2080
TableList* table, TableList* src_table,
2106
2081
message::Table &create_table_proto,
2107
2082
bool is_if_not_exists,
2108
2083
bool is_engine_set)
2110
2085
bool res= true;
2111
bool table_exists= false;
2089
By opening source table we guarantee that it exists and no concurrent
2090
DDL operation will mess with it. Later we also take an exclusive
2091
name-lock on target table name, which makes copying of .frm cursor,
2092
call to plugin::StorageEngine::createTable() and binlogging atomic
2093
against concurrent DML and DDL operations on target table.
2094
Thus by holding both these "locks" we ensure that our statement is
2095
properly isolated from all concurrent operations which matter.
2097
if (session->open_tables_from_list(&src_table, ¬_used))
2100
TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2101
src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2114
2106
Check that destination tables does not exist. Note that its name
2127
bool was_created= create_table_wrapper(*session,
2129
destination_identifier,
2120
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2121
src_identifier, is_engine_set);
2132
2122
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2134
2124
(void) session->rm_temporary_table(destination_identifier, true);
2174
2164
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
2165
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
source_identifier, is_engine_set);
2166
src_identifier, is_engine_set);
2179
2169
// So we blew the creation of the table, and we scramble to clean up
2202
2192
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2193
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2194
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2205
2195
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2196
ER_TABLE_EXISTS_ERROR,warn_buff);
2201
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());