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
#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>
39
#include <drizzled/table_identifier.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>
54
#include <boost/unordered_set.hpp>
56
52
using namespace std;
61
bool is_primary_key(KeyInfo *key_info)
57
extern plugin::StorageEngine *myisam_engine;
58
extern pid_t current_pid;
60
bool is_primary_key(KEY *key_info)
63
62
static const char * primary_key_name="PRIMARY";
64
63
return (strcmp(key_info->name, primary_key_name)==0);
108
void write_bin_log(Session *session, const std::string &query)
110
TransactionServices &transaction_services= TransactionServices::singleton();
111
transaction_services.rawStatement(*session, query);
107
void write_bin_log(Session *session,
110
TransactionServices &transaction_services= TransactionServices::singleton();
111
transaction_services.rawStatement(session, query);
115
/* Should should be refactored to go away */
116
void write_bin_log_drop_table(Session *session, bool if_exists, const char *db_name, const char *table_name)
118
TransactionServices &transaction_services= TransactionServices::singleton();
122
built_query.append("DROP TABLE IF EXISTS ");
124
built_query.append("DROP TABLE ");
126
built_query.append("`");
127
if (session->db.empty() || strcmp(db_name, session->db.c_str()) != 0)
129
built_query.append(db_name);
130
built_query.append("`.`");
133
built_query.append(table_name);
134
built_query.append("`");
135
transaction_services.rawStatement(session, built_query);
115
139
Execute the drop of a normal or temporary table
142
mysql_rm_table_part2()
119
143
session Thread Cursor
120
144
tables Tables to drop
121
145
if_exists If set, don't give an error if table doesn't exists.
122
146
In this case we give an warning of level 'NOTE'
123
147
drop_temporary Only drop temporary tables
126
150
When logging to the binary log, we should log
127
151
tmp_tables and transactional tables as separate statements if we
128
152
are in a transaction; This is needed to get these tables into the
138
162
-1 Thread was killed
141
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
165
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
144
168
TableList *table;
145
util::string::vector wrong_tables;
147
171
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
173
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
176
If we have the table in the definition cache, we don't have to check the
177
.frm cursor to find if the table is a normal table (not view) and what
181
for (table= tables; table; table= table->next_local)
183
TableIdentifier identifier(table->db, table->table_name);
185
table->db_type= NULL;
187
if ((share= TableShare::getShare(identifier)))
189
table->db_type= share->db_type();
193
if (not drop_temporary && lock_table_names_exclusively(session, tables))
195
pthread_mutex_unlock(&LOCK_open);
199
/* Don't give warnings for not found errors, as we already generate notes */
200
session->no_warnings_for_error= 1;
202
for (table= tables; table; table= table->next_local)
206
error= session->drop_temporary_table(table);
210
// removed temporary table
214
goto err_with_placeholders;
216
// temporary table not found
220
if (drop_temporary == false)
223
abort_locked_tables(session, db, table->table_name);
224
remove_table_from_cache(session, db, table->table_name,
225
RTFC_WAIT_OTHER_THREAD_FLAG |
226
RTFC_CHECK_KILLED_FLAG);
228
If the table was used in lock tables, remember it so that
229
unlock_table_names can free it
231
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
232
table->table= locked_table;
237
goto err_with_placeholders;
240
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? message::Table::INTERNAL : message::Table::STANDARD);
242
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
244
// Table was not found on disk and table can't be created from engine
246
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
247
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
175
// temporary table not found
254
error= plugin::StorageEngine::dropTable(*session, identifier);
256
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())
259
session->clear_error();
262
if (error == HA_ERR_ROW_IS_REFERENCED)
264
/* the table is referenced by a foreign key constraint */
265
foreign_key_error= true;
269
if (error == 0 || (if_exists && foreign_key_error == false))
271
TransactionServices &transaction_services= TransactionServices::singleton();
272
transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
277
if (wrong_tables.length())
278
wrong_tables.append(',');
279
wrong_tables.append(String(table->table_name,system_charset_info));
283
It's safe to unlock LOCK_open: we have an exclusive lock
286
pthread_mutex_unlock(&LOCK_open);
289
if (wrong_tables.length())
259
291
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
293
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
table_error.c_str());
294
wrong_tables.c_ptr());
508
523
(*timestamps_with_niladic)++;
512
526
sql_field->unireg_check= Field::NONE;
515
528
else if (sql_field->unireg_check != Field::NONE)
517
529
(*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:
534
sql_field->pack_flag=(0 |
535
f_settype((uint32_t) sql_field->sql_type));
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)
541
static int mysql_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
KEY **key_info_buffer,
549
int select_field_count)
551
551
const char *key_name;
552
552
CreateField *sql_field,*dup_field;
553
553
uint field,null_fields,blob_columns,max_key_length;
554
554
ulong record_offset= 0;
556
KeyPartInfo *key_part_info;
556
KEY_PART_INFO *key_part_info;
557
557
int timestamps= 0, timestamps_with_niladic= 0;
559
559
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());
560
List_iterator<CreateField> it(alter_info->create_list);
561
List_iterator<CreateField> it2(alter_info->create_list);
562
562
uint32_t total_uneven_bit_length= 0;
564
564
plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
1200
1185
key_info->name=(char*) key_name;
1204
1188
if (!key_info->name || check_column_name(key_info->name))
1206
1190
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1210
1193
if (!(key_info->flags & HA_NULL_PART_KEY))
1215
1195
key_info->key_length=(uint16_t) key_length;
1217
1196
if (key_length > max_key_length)
1219
1198
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1226
1203
if (!unique_key && !primary_key &&
1227
1204
(engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1229
1206
my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1233
1209
if (auto_increment > 0)
1235
1211
my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1238
1214
/* Sort keys in optimized order */
1239
internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
1215
internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KEY),
1240
1216
(qsort_cmp) sort_keys);
1242
1218
/* Check fields. */
1243
it= alter_info->create_list.begin();
1244
1220
while ((sql_field=it++))
1246
1222
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1248
1224
if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1249
1225
!sql_field->def &&
1250
(sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
1226
sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1251
1227
(sql_field->flags & NOT_NULL_FLAG) &&
1252
1228
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1465
1440
assert(identifier.getTableName() == table_proto.name());
1466
1441
db_options= create_info->table_options;
1443
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1444
db_options|=HA_OPTION_PACK_RECORD;
1468
1446
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1470
1448
/* 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))
1449
if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1452
&key_info_buffer, &key_count,
1453
select_field_count))
1477
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1455
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1478
1456
error= locked_create_event(session,
1846
1824
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1825
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"));
1826
session->client->store(table_name);
1827
session->client->store(operator_name);
1828
session->client->store(STRING_WITH_LEN("error"));
1851
1829
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);
1831
session->client->store(buff, length);
1832
transaction_services.ha_autocommit_or_rollback(session, false);
1855
1833
session->endTransaction(COMMIT);
1856
1834
session->close_thread_tables();
1857
session->getLex()->reset_query_tables_list(false);
1835
lex->reset_query_tables_list(false);
1858
1836
table->table=0; // For query cache
1859
if (session->getClient()->flush())
1837
if (session->client->flush())
1864
1842
/* Close all instances of the table to allow repair to rename files */
1865
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1843
if (lock_type == TL_WRITE && table->table->s->version)
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);
1845
pthread_mutex_lock(&LOCK_open); /* Lock type is TL_WRITE and we lock to repair the table */
1846
const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
1847
"Waiting to get writelock");
1848
mysql_lock_abort(session,table->table);
1849
remove_table_from_cache(session, table->table->s->getSchemaName(),
1850
table->table->s->table_name.str,
1851
RTFC_WAIT_OTHER_THREAD_FLAG |
1852
RTFC_CHECK_KILLED_FLAG);
1873
1853
session->exit_cond(old_message);
1874
if (session->getKilled())
1854
if (session->killed)
1876
1856
open_for_modify= 0;
1883
session->getLex()->cleanup_after_one_table_open();
1863
lex->cleanup_after_one_table_open();
1884
1864
session->clear_error(); // these errors shouldn't get client
1886
List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1866
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1867
DRIZZLE_ERROR *err;
1888
1868
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,
1870
session->client->store(table_name);
1871
session->client->store(operator_name);
1872
session->client->store(warning_level_names[err->level].str,
1893
1873
warning_level_names[err->level].length);
1894
session->getClient()->store(err->msg);
1895
if (session->getClient()->flush())
1874
session->client->store(err->msg);
1875
if (session->client->flush())
1898
1878
drizzle_reset_errors(session, true);
1900
session->getClient()->store(table_name.c_str());
1901
session->getClient()->store(operator_name);
1880
session->client->store(table_name);
1881
session->client->store(operator_name);
1903
1883
switch (result_code) {
1904
1884
case HA_ADMIN_NOT_IMPLEMENTED:
1906
1886
char buf[ERRMSGSIZE+20];
1907
1887
uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1888
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
session->getClient()->store(STRING_WITH_LEN("note"));
1910
session->getClient()->store(buf, length);
1889
session->client->store(STRING_WITH_LEN("note"));
1890
session->client->store(buf, length);
1914
1894
case HA_ADMIN_OK:
1915
session->getClient()->store(STRING_WITH_LEN("status"));
1916
session->getClient()->store(STRING_WITH_LEN("OK"));
1895
session->client->store(STRING_WITH_LEN("status"));
1896
session->client->store(STRING_WITH_LEN("OK"));
1919
1899
case HA_ADMIN_FAILED:
1920
session->getClient()->store(STRING_WITH_LEN("status"));
1921
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1900
session->client->store(STRING_WITH_LEN("status"));
1901
session->client->store(STRING_WITH_LEN("Operation failed"));
1924
1904
case HA_ADMIN_REJECT:
1925
session->getClient()->store(STRING_WITH_LEN("status"));
1926
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1905
session->client->store(STRING_WITH_LEN("status"));
1906
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1927
1907
open_for_modify= false;
1930
1910
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"));
1911
session->client->store(STRING_WITH_LEN("status"));
1912
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1935
1915
case HA_ADMIN_CORRUPT:
1936
session->getClient()->store(STRING_WITH_LEN("error"));
1937
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1916
session->client->store(STRING_WITH_LEN("error"));
1917
session->client->store(STRING_WITH_LEN("Corrupt"));
1941
1921
case HA_ADMIN_INVALID:
1942
session->getClient()->store(STRING_WITH_LEN("error"));
1943
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1922
session->client->store(STRING_WITH_LEN("error"));
1923
session->client->store(STRING_WITH_LEN("Invalid argument"));
1946
1926
default: // Probably HA_ADMIN_INTERNAL_ERROR
1958
1938
if (table->table)
1960
1940
if (fatal_error)
1962
table->table->getMutableShare()->resetVersion(); // Force close of table
1941
table->table->s->version=0; // Force close of table
1964
1942
else if (open_for_modify)
1966
if (table->table->getShare()->getType())
1944
if (table->table->s->tmp_table)
1968
1945
table->table->cursor->info(HA_STATUS_CONST);
1972
boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1948
pthread_mutex_lock(&LOCK_open);
1949
remove_table_from_cache(session, table->table->s->getSchemaName(),
1950
table->table->s->table_name.str, RTFC_NO_FLAG);
1951
pthread_mutex_unlock(&LOCK_open);
1978
transaction_services.autocommitOrRollback(*session, false);
1955
transaction_services.ha_autocommit_or_rollback(session, false);
1979
1956
session->endTransaction(COMMIT);
1980
1957
session->close_thread_tables();
1981
1958
table->table=0; // For query cache
1982
if (session->getClient()->flush())
1959
if (session->client->flush())
1976
We have to write the query before we unlock the named table.
1978
Since temporary tables are not replicated under row-based
1979
replication, CREATE TABLE ... LIKE ... needs special
1980
treatement. We have four cases to consider, according to the
1981
following decision table:
1983
==== ========= ========= ==============================
1984
Case Target Source Write to binary log
1985
==== ========= ========= ==============================
1986
1 normal normal Original statement
1987
2 normal temporary Generated statement
1988
3 temporary normal Nothing
1989
4 temporary temporary Nothing
1990
==== ========= ========= ==============================
1992
static bool replicateCreateTableLike(Session *session, TableList *table, Table *name_lock,
1993
bool is_src_table_tmp, bool is_if_not_exists)
1995
if (is_src_table_tmp)
1998
String query(buf, sizeof(buf), system_charset_info);
1999
query.length(0); // Have to zero it since constructor doesn't
2003
Here we open the destination table, on which we already have
2004
name-lock. This is needed for store_create_info() to work.
2005
The table will be closed by unlink_open_table() at the end
2008
table->table= name_lock;
2009
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2010
if (session->reopen_name_locked_table(table, false))
2012
pthread_mutex_unlock(&LOCK_open);
2015
pthread_mutex_unlock(&LOCK_open);
2017
int result= store_create_info(table, &query, is_if_not_exists);
2019
assert(result == 0); // store_create_info() always return 0
2020
write_bin_log(session, query.ptr());
2024
write_bin_log(session, session->query.c_str());
1999
2031
Create a new table by copying from source table
2001
2033
Altough exclusive name-lock on target table protects us from concurrent
2002
2034
DML and DDL operations on it we still want to wrap .FRM creation and call
2003
2035
to plugin::StorageEngine::createTable() in critical section protected by
2004
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2036
LOCK_open in order to provide minimal atomicity against operations which
2005
2037
disregard name-locks, like I_S implementation, for example. This is a
2006
2038
temporary and should not be copied. Instead we should fix our code to
2007
2039
always honor name-locks.
2009
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2041
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2010
2042
during the call to plugin::StorageEngine::createTable().
2011
2043
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,
2045
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2046
TableIdentifier &destination_identifier,
2047
TableIdentifier &src_table,
2017
2048
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);
2050
int protoerr= EEXIST;
2051
message::Table new_proto;
2052
message::Table src_proto;
2054
protoerr= plugin::StorageEngine::getTableDefinition(session,
2057
new_proto.CopyFrom(src_proto);
2034
2059
if (destination_identifier.isTmp())
2036
new_table_message.set_type(message::Table::TEMPORARY);
2061
new_proto.set_type(message::Table::TEMPORARY);
2040
new_table_message.set_type(message::Table::STANDARD);
2065
new_proto.set_type(message::Table::STANDARD);
2043
2068
if (is_engine_set)
2045
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2070
message::Table::StorageEngine *protoengine;
2072
protoengine= new_proto.mutable_engine();
2073
protoengine->set_name(create_table_proto.engine().name());
2048
2076
{ // 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());
2077
new_proto.set_name(create_table_proto.name());
2078
new_proto.set_schema(create_table_proto.schema());
2079
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++)
2082
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);
2084
if (errno == ENOENT)
2085
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2087
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2072
2093
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).
2094
creation, instead create the table directly (for both normal
2095
and temporary tables).
2075
bool success= plugin::StorageEngine::createTable(session,
2076
destination_identifier,
2079
if (success && not destination_identifier.isTmp())
2081
TransactionServices &transaction_services= TransactionServices::singleton();
2082
transaction_services.createTable(session, new_table_message);
2097
int err= plugin::StorageEngine::createTable(session,
2098
destination_identifier,
2101
return err ? false : true;
2089
2105
Create a table identical to the specified table
2108
mysql_create_like_table()
2093
2109
session Thread object
2094
2110
table Table list element for target table
2095
2111
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,
2119
bool mysql_create_like_table(Session* session,
2120
TableIdentifier &destination_identifier,
2121
TableList* table, TableList* src_table,
2122
message::Table &create_table_proto,
2123
bool is_if_not_exists,
2126
Table *name_lock= 0;
2127
char *db= table->db;
2128
char *table_name= table->table_name;
2110
2129
bool res= true;
2111
bool table_exists= false;
2134
By opening source table we guarantee that it exists and no concurrent
2135
DDL operation will mess with it. Later we also take an exclusive
2136
name-lock on target table name, which makes copying of .frm cursor,
2137
call to plugin::StorageEngine::createTable() and binlogging atomic
2138
against concurrent DML and DDL operations on target table.
2139
Thus by holding both these "locks" we ensure that our statement is
2140
properly isolated from all concurrent operations which matter.
2142
if (session->open_tables_from_list(&src_table, ¬_used))
2145
TableIdentifier src_identifier(src_table->table->s->getSchemaName(),
2146
src_table->table->s->table_name.str, src_table->table->s->tmp_table);
2114
2151
Check that destination tables does not exist. Note that its name
2115
2152
was already checked when it was added to the table list.
2117
For temporary tables we don't aim to grab locks.
2154
bool table_exists= false;
2119
2155
if (destination_identifier.isTmp())
2121
if (session->find_temporary_table(destination_identifier))
2157
if (session->find_temporary_table(db, table_name))
2123
2159
table_exists= true;
2127
bool was_created= create_table_wrapper(*session,
2129
destination_identifier,
2132
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2134
(void) session->rm_temporary_table(destination_identifier, true);
2136
else if (not session->open_temporary_table(destination_identifier))
2138
// We created, but we can't open... also, a hack.
2139
(void) session->rm_temporary_table(destination_identifier, true);
2147
else // Standard table which will require locks.
2149
Table *name_lock= 0;
2151
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2164
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2155
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2168
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2156
2169
session->unlink_open_table(name_lock);
2170
pthread_mutex_unlock(&LOCK_open);
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);
2202
else // Otherwise we create the table
2204
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2205
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2206
src_identifier, is_engine_set);
2207
pthread_mutex_unlock(&LOCK_open);
2209
// So we blew the creation of the table, and we scramble to clean up
2210
// anything that might have been created (read... it is a hack)
2211
if (not was_created)
2213
if (destination_identifier.isTmp())
2215
(void) session->rm_temporary_table(destination_identifier);
2219
quick_rm_table(*session, destination_identifier);
2222
else if (destination_identifier.isTmp() && not session->open_temporary_table(destination_identifier))
2224
// We created, but we can't open... also, a hack.
2225
(void) session->rm_temporary_table(destination_identifier);
2229
if (not destination_identifier.isTmp())
2231
bool rc= replicateCreateTableLike(session, table, name_lock, (src_table->table->s->tmp_table), is_if_not_exists);
2241
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2242
session->unlink_open_table(name_lock);
2243
pthread_mutex_unlock(&LOCK_open);
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2250
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
2252
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2254
return(mysql_admin_table(session, tables, check_opt,
2224
2255
"analyze", lock_type, true,
2225
2256
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2260
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
2262
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2264
return(mysql_admin_table(session, tables, check_opt,
2234
2265
"check", lock_type,
2236
2267
&Cursor::ha_check));
2271
bool mysql_checksum_table(Session *session, TableList *tables,
2275
List<Item> field_list;
2278
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2279
item->maybe_null= 1;
2280
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2281
MY_INT64_NUM_DECIMAL_DIGITS));
2282
item->maybe_null= 1;
2283
if (session->client->sendFields(&field_list))
2286
/* Open one table after the other to keep lock time as short as possible. */
2287
for (table= tables; table; table= table->next_local)
2289
char table_name[NAME_LEN*2+2];
2292
snprintf(table_name, sizeof(table_name), "%s.%s",table->db,table->table_name);
2294
t= table->table= session->openTableLock(table, TL_READ);
2295
session->clear_error(); // these errors shouldn't get client
2297
session->client->store(table_name);
2301
/* Table didn't exist */
2302
session->client->store();
2303
session->clear_error();
2308
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2310
if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
2312
session->client->store((uint64_t)t->cursor->checksum());
2316
/* calculating table's checksum */
2317
internal::ha_checksum crc= 0;
2318
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2320
t->use_all_columns();
2322
if (t->cursor->ha_rnd_init(1))
2323
session->client->store();
2328
internal::ha_checksum row_crc= 0;
2329
int error= t->cursor->rnd_next(t->record[0]);
2330
if (unlikely(error))
2332
if (error == HA_ERR_RECORD_DELETED)
2336
if (t->s->null_bytes)
2338
/* fix undefined null bits */
2339
t->record[0][t->s->null_bytes-1] |= null_mask;
2340
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2341
t->record[0][0] |= 1;
2343
row_crc= internal::my_checksum(row_crc, t->record[0], t->s->null_bytes);
2346
for (uint32_t i= 0; i < t->s->fields; i++ )
2348
Field *f= t->field[i];
2349
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2350
(f->type() == DRIZZLE_TYPE_VARCHAR))
2354
row_crc= internal::my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2357
row_crc= internal::my_checksum(row_crc, f->ptr,
2363
session->client->store((uint64_t)crc);
2364
t->cursor->ha_rnd_end();
2367
session->clear_error();
2368
session->close_thread_tables();
2369
table->table=0; // For query cache
2371
if (session->client->flush())
2379
session->close_thread_tables(); // Shouldn't be needed
2239
2385
} /* namespace drizzled */