77
static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
78
static char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
61
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
62
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
80
64
static bool prepare_blob_field(Session *session, CreateField *sql_field);
82
void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
66
void set_table_default_charset(HA_CREATE_INFO *create_info, char *db)
85
69
If the table character set was not given explicitly,
86
70
let's fetch the database default character set and
87
71
apply it to the table.
89
identifier::Schema identifier(db);
90
73
if (create_info->default_table_charset == NULL)
91
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
74
create_info->default_table_charset= get_default_db_collation(db);
78
Translate a cursor name to a table name (WL #1324).
81
filename_to_tablename()
84
to_length The size of the table name buffer.
89
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
93
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
95
/* Temporary table name. */
96
length= strlen(strncpy(to, from, to_length));
100
for (; *from && length < to_length; length++, from++)
107
/* We've found an escaped char - skip the @ */
110
/* There will be a two-position hex-char version of the char */
111
for (int x=1; x >= 0; x--)
113
if (*from >= '0' && *from <= '9')
114
to[length] += ((*from++ - '0') << (4 * x));
115
else if (*from >= 'a' && *from <= 'f')
116
to[length] += ((*from++ - 'a' + 10) << (4 * x));
118
/* Backup because we advanced extra in the inner loop */
128
Translate a table name to a cursor name (WL #1324).
131
tablename_to_filename()
133
to OUT The cursor name
134
to_length The size of the cursor name buffer.
137
true if errors happen. false on success.
139
bool tablename_to_filename(const char *from, char *to, size_t to_length)
143
for (; *from && length < to_length; length++, from++)
145
if ((*from >= '0' && *from <= '9') ||
146
(*from >= 'A' && *from <= 'Z') ||
147
(*from >= 'a' && *from <= 'z') ||
148
/* OSX defines an extra set of high-bit and multi-byte characters
149
that cannot be used on the filesystem. Instead of trying to sort
150
those out, we'll just escape encode all high-bit-set chars on OSX.
151
It won't really hurt anything - it'll just make some filenames ugly. */
152
#if !defined(TARGET_OS_OSX)
153
((unsigned char)*from >= 128) ||
163
if (length + 3 >= to_length)
166
/* We need to escape this char in a way that can be reversed */
168
to[length++]= hexchars[(*from >> 4) & 15];
169
to[length]= hexchars[(*from) & 15];
172
if (check_if_legal_tablename(to) &&
173
length + 4 < to_length)
175
memcpy(to + length, "@@@", 4);
183
Creates path to a cursor: drizzle_data_dir/db/table.ext
186
build_table_filename()
187
buff Where to write result
188
This may be the same as table_name.
191
table_name Table name
193
flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
194
table_name is temporary, do not change.
198
Uses database and table name, and extension to create
199
a cursor name in drizzle_data_dir. Database and table
200
names are converted from system_charset_info into "fscs".
201
Unless flags indicate a temporary table name.
202
'db' is always converted.
203
'ext' is not converted.
205
The conversion suppression is required for ALTER Table. This
206
statement creates intermediate tables. These are regular
207
(non-temporary) tables with a temporary name. Their path names must
208
be derivable from the table name. So we cannot use
209
build_tmptable_filename() for them.
212
path length on success, 0 on failure
215
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
217
char dbbuff[FN_REFLEN];
218
char tbbuff[FN_REFLEN];
219
bool conversion_error= false;
221
memset(tbbuff, 0, sizeof(tbbuff));
222
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
223
strncpy(tbbuff, table_name, sizeof(tbbuff));
226
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
227
if (conversion_error)
229
errmsg_printf(ERRMSG_LVL_ERROR,
230
_("Table name cannot be encoded and fit within filesystem "
231
"name length restrictions."));
235
memset(dbbuff, 0, sizeof(dbbuff));
236
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
237
if (conversion_error)
239
errmsg_printf(ERRMSG_LVL_ERROR,
240
_("Schema name cannot be encoded and fit within filesystem "
241
"name length restrictions."));
246
int rootdir_len= strlen(FN_ROOTDIR);
247
string table_path(drizzle_data_home);
248
int without_rootdir= table_path.length()-rootdir_len;
250
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
251
if (without_rootdir >= 0)
253
const char *tmp= table_path.c_str()+without_rootdir;
254
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
255
table_path.append(FN_ROOTDIR);
258
table_path.append(dbbuff);
259
table_path.append(FN_ROOTDIR);
260
table_path.append(tbbuff);
262
if (bufflen < table_path.length())
265
strcpy(buff, table_path.c_str());
267
return table_path.length();
272
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
275
build_tmptable_filename()
276
session The thread handle.
277
buff Where to write result
282
Uses current_pid, thread_id, and tmp_table counter to create
283
a cursor name in drizzle_tmpdir.
286
path length on success, 0 on failure
289
static uint32_t build_tmptable_filename(Session* session,
290
char *buff, size_t bufflen)
293
ostringstream path_str, post_tmpdir_str;
296
path_str << drizzle_tmpdir;
297
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
298
post_tmpdir_str << session->thread_id << session->tmp_table++;
299
tmp= post_tmpdir_str.str();
301
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
305
if (bufflen < path_str.str().length())
308
length= unpack_filename(buff, path_str.str().c_str());
139
444
-1 Thread was killed
142
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
447
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
448
bool drop_temporary, bool dont_log_query)
145
450
TableList *table;
451
char path[FN_REFLEN];
452
uint32_t path_length= 0;
146
453
String wrong_tables;
148
455
bool foreign_key_error= false;
152
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
154
if (not drop_temporary && session->lock_table_names_exclusively(tables))
159
/* Don't give warnings for not found errors, as we already generate notes */
160
session->no_warnings_for_error= 1;
162
for (table= tables; table; table= table->next_local)
164
identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
166
error= session->drop_temporary_table(tmp_identifier);
170
// removed temporary table
457
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
460
If we have the table in the definition cache, we don't have to check the
461
.frm cursor to find if the table is a normal table (not view) and what
465
for (table= tables; table; table= table->next_local)
468
table->db_type= NULL;
469
if ((share= TableShare::getShare(table->db, table->table_name)))
470
table->db_type= share->db_type();
473
if (!drop_temporary && lock_table_names_exclusively(session, tables))
475
pthread_mutex_unlock(&LOCK_open);
479
/* Don't give warnings for not found errors, as we already generate notes */
480
session->no_warnings_for_error= 1;
482
for (table= tables; table; table= table->next_local)
485
plugin::StorageEngine *table_type;
487
error= session->drop_temporary_table(table);
491
// removed temporary table
495
goto err_with_placeholders;
497
// temporary table not found
501
table_type= table->db_type;
505
abort_locked_tables(session, db, table->table_name);
506
remove_table_from_cache(session, db, table->table_name,
507
RTFC_WAIT_OTHER_THREAD_FLAG |
508
RTFC_CHECK_KILLED_FLAG);
510
If the table was used in lock tables, remember it so that
511
unlock_table_names can free it
513
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
514
table->table= locked_table;
519
goto err_with_placeholders;
521
/* remove .frm cursor and engine files */
522
path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
525
if (drop_temporary ||
527
&& (plugin::StorageEngine::getTableDefinition(*session,
531
table->internal_tmp_table) != EEXIST))))
533
// Table was not found on disk and table can't be created from engine
535
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
536
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
176
// temporary table not found
180
if (drop_temporary == false)
183
abort_locked_tables(session, tmp_identifier);
184
table::Cache::singleton().removeTable(session, tmp_identifier,
185
RTFC_WAIT_OTHER_THREAD_FLAG |
186
RTFC_CHECK_KILLED_FLAG);
188
If the table was used in lock tables, remember it so that
189
unlock_table_names can free it
191
if ((locked_table= drop_locked_tables(session, tmp_identifier)))
192
table->table= locked_table;
194
if (session->getKilled())
200
identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
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
206
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
table->getTableName());
216
drizzled::error_t local_error;
218
/* Generate transaction event ONLY when we successfully drop */
219
if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
221
TransactionServices &transaction_services= TransactionServices::singleton();
222
transaction_services.dropTable(*session, identifier, if_exists);
226
if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
229
session->clear_error();
232
if (local_error == HA_ERR_ROW_IS_REFERENCED)
234
/* the table is referenced by a foreign key constraint */
235
foreign_key_error= true;
243
if (wrong_tables.length())
244
wrong_tables.append(',');
245
wrong_tables.append(String(table->getTableName(), system_charset_info));
249
tables->unlock_table_names();
543
error= plugin::StorageEngine::dropTable(*session, path, db,
546
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
549
session->clear_error();
552
if (error == HA_ERR_ROW_IS_REFERENCED)
554
/* the table is referenced by a foreign key constraint */
555
foreign_key_error= true;
559
if (error == 0 || (if_exists && foreign_key_error == false))
560
write_bin_log_drop_table(session, if_exists, db, table->table_name);
564
if (wrong_tables.length())
565
wrong_tables.append(',');
566
wrong_tables.append(String(table->table_name,system_charset_info));
570
It's safe to unlock LOCK_open: we have an exclusive lock
573
pthread_mutex_unlock(&LOCK_open);
253
575
if (wrong_tables.length())
255
if (not foreign_key_error)
577
if (!foreign_key_error)
257
578
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
579
wrong_tables.c_ptr());
262
582
my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
1429
bool create_table_no_lock(Session *session,
1430
const identifier::Table &identifier,
1608
bool mysql_create_table_no_lock(Session *session,
1609
const char *db, const char *table_name,
1431
1610
HA_CREATE_INFO *create_info,
1432
message::Table &table_proto,
1611
message::Table *table_proto,
1433
1612
AlterInfo *alter_info,
1434
1613
bool internal_tmp_table,
1435
uint32_t select_field_count,
1436
bool is_if_not_exists)
1614
uint32_t select_field_count)
1616
char path[FN_REFLEN];
1617
uint32_t path_length;
1438
1618
uint db_options, key_count;
1439
KeyInfo *key_info_buffer;
1619
KEY *key_info_buffer;
1440
1621
bool error= true;
1442
1624
/* Check for duplicate fields and check type of table to create */
1443
if (not alter_info->create_list.elements)
1625
if (!alter_info->create_list.elements)
1445
1627
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1449
assert(identifier.getTableName() == table_proto.name());
1631
assert(strcmp(table_name,table_proto->name().c_str())==0);
1632
if (check_engine(session, table_name, create_info))
1450
1634
db_options= create_info->table_options;
1452
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1454
/* Build a Table object to pass down to the engine, and the do the actual create. */
1455
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1458
&key_info_buffer, &key_count,
1459
select_field_count))
1461
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
error= locked_create_event(session,
1469
db_options, key_count,
1635
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1636
db_options|=HA_OPTION_PACK_RECORD;
1637
if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1639
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1643
set_table_default_charset(create_info, (char*) db);
1645
if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1647
&db_options, cursor,
1648
&key_info_buffer, &key_count,
1649
select_field_count))
1652
/* Check if table exists */
1653
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1655
path_length= build_tmptable_filename(session, path, sizeof(path));
1660
/* check if the table name contains FN_DEVCHAR when defined */
1661
if (strchr(table_name, FN_DEVCHAR))
1663
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
1667
path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
1670
/* Check if table already exists */
1671
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1672
session->find_temporary_table(db, table_name))
1674
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1676
create_info->table_existed= 1; // Mark that table existed
1677
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1678
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1683
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1687
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1688
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1690
if (plugin::StorageEngine::getTableDefinition(*session, path, db, table_name, internal_tmp_table)==EEXIST)
1692
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1695
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1696
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1698
create_info->table_existed= 1; // Mark that table existed
1701
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1703
goto unlock_and_end;
1706
We don't assert here, but check the result, because the table could be
1707
in the table definition cache and in the same time the .frm could be
1708
missing from the disk, in case of manual intervention which deletes
1709
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1710
Then she could create the table. This case is pretty obscure and
1711
therefore we don't introduce a new error message only for it.
1713
if (TableShare::getShare(db, table_name))
1715
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1716
goto unlock_and_end;
1721
Check that table with given name does not already
1722
exist in any storage engine. In such a case it should
1723
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1724
unless user specified CREATE TABLE IF EXISTS
1725
The LOCK_open mutex has been locked to make sure no
1726
one else is attempting to discover the table. Since
1727
it's not on disk as a frm cursor, no one could be using it!
1729
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1731
bool create_if_not_exists =
1732
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1734
char table_path[FN_REFLEN];
1735
uint32_t table_path_length;
1737
table_path_length= build_table_filename(table_path, sizeof(table_path),
1738
db, table_name, false);
1740
int retcode= plugin::StorageEngine::getTableDefinition(*session, table_path, db, table_name, false);
1744
/* Normal case, no table exists. we can go and create it */
1747
if (create_if_not_exists)
1750
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1751
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1753
create_info->table_existed= 1; // Mark that table existed
1754
goto unlock_and_end;
1756
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1757
goto unlock_and_end;
1759
my_error(retcode, MYF(0),table_name);
1760
goto unlock_and_end;
1764
session->set_proc_info("creating table");
1765
create_info->table_existed= 0; // Mark that table is created
1767
create_info->table_options=db_options;
1769
if (rea_create_table(session, path, db, table_name,
1771
create_info, alter_info->create_list,
1772
key_count, key_info_buffer))
1773
goto unlock_and_end;
1775
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1777
/* Open table and put in temporary table list */
1778
if (!(session->open_temporary_table(path, db, table_name)))
1780
(void) session->rm_temporary_table(create_info->db_type, path);
1781
goto unlock_and_end;
1786
Don't write statement if:
1787
- It is an internal temporary table,
1788
- Row-based logging is used and it we are creating a temporary table, or
1789
- The binary log is not open.
1790
Otherwise, the statement shall be binlogged.
1792
if (!internal_tmp_table &&
1793
((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1794
write_bin_log(session, session->query, session->query_length);
1797
pthread_mutex_unlock(&LOCK_open);
1473
1800
session->set_proc_info("After create");
1479
@note the following two methods implement create [temporary] table.
1807
Database locking aware wrapper for mysql_create_table_no_lock(),
1481
static bool drizzle_create_table(Session *session,
1482
const identifier::Table &identifier,
1483
HA_CREATE_INFO *create_info,
1484
message::Table &table_proto,
1485
AlterInfo *alter_info,
1486
bool internal_tmp_table,
1487
uint32_t select_field_count,
1488
bool is_if_not_exists)
1810
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1811
HA_CREATE_INFO *create_info,
1812
message::Table *table_proto,
1813
AlterInfo *alter_info,
1814
bool internal_tmp_table,
1815
uint32_t select_field_count)
1490
1817
Table *name_lock= NULL;
1493
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1497
else if (name_lock == NULL)
1499
if (is_if_not_exists)
1501
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1503
identifier.getTableName().c_str());
1504
create_info->table_existed= 1;
1509
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1820
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1822
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
1515
result= create_table_no_lock(session,
1827
if (name_lock == NULL)
1829
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1831
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1832
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1834
create_info->table_existed= 1;
1839
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1846
result= mysql_create_table_no_lock(session, db, table_name, create_info,
1850
select_field_count);
1527
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1855
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1528
1856
session->unlink_open_table(name_lock);
1857
pthread_mutex_unlock(&LOCK_open);
1531
1860
return(result);
1888
2219
char buf[ERRMSGSIZE+20];
1889
2220
uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
2221
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
session->getClient()->store(STRING_WITH_LEN("note"));
1892
session->getClient()->store(buf, length);
2222
session->client->store(STRING_WITH_LEN("note"));
2223
session->client->store(buf, length);
1896
2227
case HA_ADMIN_OK:
1897
session->getClient()->store(STRING_WITH_LEN("status"));
1898
session->getClient()->store(STRING_WITH_LEN("OK"));
2228
session->client->store(STRING_WITH_LEN("status"));
2229
session->client->store(STRING_WITH_LEN("OK"));
1901
2232
case HA_ADMIN_FAILED:
1902
session->getClient()->store(STRING_WITH_LEN("status"));
1903
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
2233
session->client->store(STRING_WITH_LEN("status"));
2234
session->client->store(STRING_WITH_LEN("Operation failed"));
1906
2237
case HA_ADMIN_REJECT:
1907
session->getClient()->store(STRING_WITH_LEN("status"));
1908
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
2238
session->client->store(STRING_WITH_LEN("status"));
2239
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
2240
open_for_modify= false;
1912
2243
case HA_ADMIN_ALREADY_DONE:
1913
session->getClient()->store(STRING_WITH_LEN("status"));
1914
session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
2244
session->client->store(STRING_WITH_LEN("status"));
2245
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1917
2248
case HA_ADMIN_CORRUPT:
1918
session->getClient()->store(STRING_WITH_LEN("error"));
1919
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
2249
session->client->store(STRING_WITH_LEN("error"));
2250
session->client->store(STRING_WITH_LEN("Corrupt"));
1923
2254
case HA_ADMIN_INVALID:
1924
session->getClient()->store(STRING_WITH_LEN("error"));
1925
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
2255
session->client->store(STRING_WITH_LEN("error"));
2256
session->client->store(STRING_WITH_LEN("Invalid argument"));
2259
case HA_ADMIN_TRY_ALTER:
2262
This is currently used only by InnoDB. ha_innobase::optimize() answers
2263
"try with alter", so here we close the table, do an ALTER Table,
2264
reopen the table and do ha_innobase::analyze() on it.
2266
ha_autocommit_or_rollback(session, 0);
2267
session->close_thread_tables();
2268
TableList *save_next_local= table->next_local,
2269
*save_next_global= table->next_global;
2270
table->next_local= table->next_global= 0;
2271
result_code= mysql_recreate_table(session, table);
2273
mysql_recreate_table() can push OK or ERROR.
2274
Clear 'OK' status. If there is an error, keep it:
2275
we will store the error message in a result set row
2278
if (session->main_da.is_ok())
2279
session->main_da.reset_diagnostics_area();
2280
ha_autocommit_or_rollback(session, 0);
2281
session->close_thread_tables();
2282
if (!result_code) // recreation went ok
2284
if ((table->table= session->openTableLock(table, lock_type)) &&
2285
((result_code= table->table->cursor->ha_analyze(session, check_opt)) > 0))
2286
result_code= 0; // analyze went ok
2288
if (result_code) // either mysql_recreate_table or analyze failed
2290
assert(session->is_error());
2291
if (session->is_error())
2293
const char *err_msg= session->main_da.message();
2294
/* Hijack the row already in-progress. */
2295
session->client->store(STRING_WITH_LEN("error"));
2296
session->client->store(err_msg);
2297
(void)session->client->flush();
2298
/* Start off another row for HA_ADMIN_FAILED */
2299
session->client->store(table_name);
2300
session->client->store(operator_name);
2301
session->clear_error();
2304
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
2305
table->next_local= save_next_local;
2306
table->next_global= save_next_global;
2307
goto send_result_message;
2309
case HA_ADMIN_NEEDS_UPGRADE:
2310
case HA_ADMIN_NEEDS_ALTER:
2312
char buf[ERRMSGSIZE];
2315
session->client->store(STRING_WITH_LEN("error"));
2316
length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
2317
session->client->store(buf, length);
1928
2322
default: // Probably HA_ADMIN_INTERNAL_ERROR
2371
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2373
return(mysql_admin_table(session, tables, check_opt,
2374
"optimize", TL_WRITE, 1,0,0,0,
2375
&Cursor::ha_optimize));
2379
Create a table identical to the specified table
2382
mysql_create_like_table()
2383
session Thread object
2384
table Table list element for target table
2385
src_table Table list element for source table
2386
create_info Create info
2393
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2394
drizzled::message::Table& create_table_proto,
2395
HA_CREATE_INFO *create_info)
2397
Table *name_lock= 0;
2398
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2399
uint32_t dst_path_length;
2400
char *db= table->db;
2401
char *table_name= table->table_name;
2405
message::Table src_proto;
2408
By opening source table we guarantee that it exists and no concurrent
2409
DDL operation will mess with it. Later we also take an exclusive
2410
name-lock on target table name, which makes copying of .frm cursor,
2411
call to plugin::StorageEngine::createTable() and binlogging atomic
2412
against concurrent DML and DDL operations on target table.
2413
Thus by holding both these "locks" we ensure that our statement is
2414
properly isolated from all concurrent operations which matter.
2416
if (session->open_tables_from_list(&src_table, ¬_used))
2419
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2423
Check that destination tables does not exist. Note that its name
2424
was already checked when it was added to the table list.
2426
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2428
if (session->find_temporary_table(db, table_name))
2430
dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2434
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2438
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2439
db, table_name, false);
2440
if (plugin::StorageEngine::getTableDefinition(*session, dst_path, db, table_name, false) == EEXIST)
1981
2445
Create a new table by copying from source table
1983
2447
Altough exclusive name-lock on target table protects us from concurrent
1984
2448
DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2449
to plugin::StorageEngine::createTable() in critical section protected by
1986
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2450
LOCK_open in order to provide minimal atomicity against operations which
1987
2451
disregard name-locks, like I_S implementation, for example. This is a
1988
2452
temporary and should not be copied. Instead we should fix our code to
1989
2453
always honor name-locks.
1991
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2455
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2456
during the call to plugin::StorageEngine::createTable().
1993
2457
See bug #28614 for more info.
1995
static bool create_table_wrapper(Session &session,
1996
const message::Table& create_table_proto,
1997
identifier::Table::const_reference destination_identifier,
1998
identifier::Table::const_reference source_identifier,
2001
// We require an additional table message because during parsing we used
2002
// a "new" message and it will not have all of the information that the
2003
// source table message would have.
2004
message::Table new_table_message;
2005
drizzled::error_t error;
2007
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2009
if (not source_table_message)
2011
my_error(ER_TABLE_UNKNOWN, source_identifier);
2015
new_table_message.CopyFrom(*source_table_message);
2017
if (destination_identifier.isTmp())
2019
new_table_message.set_type(message::Table::TEMPORARY);
2459
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2461
int protoerr= EEXIST;
2463
if (src_table->schema_table)
2466
If engine was not specified and we are reading from the I_S, then we need to
2467
toss an error. This should go away later on when we straighten out the
2470
if (! (create_info->used_fields & HA_CREATE_USED_ENGINE))
2472
pthread_mutex_unlock(&LOCK_open);
2473
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2474
"INFORMATION_ENGINE",
2479
if (create_like_schema_frm(session, src_table, create_info, &src_proto))
2481
pthread_mutex_unlock(&LOCK_open);
2487
protoerr= plugin::StorageEngine::getTableDefinition(*session,
2495
message::Table new_proto(src_proto);
2497
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
2499
message::Table::StorageEngine *protoengine;
2501
protoengine= new_proto.mutable_engine();
2502
protoengine->set_name(create_table_proto.engine().name());
2505
if (protoerr == EEXIST)
2507
plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
2508
new_proto.engine().name());
2510
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2512
string dst_proto_path(dst_path);
2513
dst_proto_path.append(".dfe");
2515
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
2525
if (my_errno == ENOENT)
2526
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2528
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2529
pthread_mutex_unlock(&LOCK_open);
2534
As mysql_truncate don't work on a new table at this stage of
2535
creation, instead create the table directly (for both normal
2536
and temporary tables).
2538
err= plugin::StorageEngine::createTable(*session, dst_path, db, table_name, *create_info,
2541
pthread_mutex_unlock(&LOCK_open);
2543
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2545
if (err || !session->open_temporary_table(dst_path, db, table_name))
2547
(void) session->rm_temporary_table(create_info->db_type, dst_path);
2553
(void) quick_rm_table(*session, db,
2559
We have to write the query before we unlock the tables.
2563
Since temporary tables are not replicated under row-based
2564
replication, CREATE TABLE ... LIKE ... needs special
2565
treatement. We have four cases to consider, according to the
2566
following decision table:
2568
==== ========= ========= ==============================
2569
Case Target Source Write to binary log
2570
==== ========= ========= ==============================
2571
1 normal normal Original statement
2572
2 normal temporary Generated statement
2573
3 temporary normal Nothing
2574
4 temporary temporary Nothing
2575
==== ========= ========= ==============================
2577
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2579
if (src_table->table->s->tmp_table) // Case 2
2582
String query(buf, sizeof(buf), system_charset_info);
2583
query.length(0); // Have to zero it since constructor doesn't
2587
Here we open the destination table, on which we already have
2588
name-lock. This is needed for store_create_info() to work.
2589
The table will be closed by unlink_open_table() at the end
2592
table->table= name_lock;
2593
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2594
if (session->reopen_name_locked_table(table, false))
2596
pthread_mutex_unlock(&LOCK_open);
2599
pthread_mutex_unlock(&LOCK_open);
2601
int result= store_create_info(table, &query, create_info);
2603
assert(result == 0); // store_create_info() always return 0
2604
write_bin_log(session, query.ptr(), query.length());
2607
write_bin_log(session, session->query, session->query_length);
2615
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2617
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2618
snprintf(warn_buff, sizeof(warn_buff),
2619
ER(ER_TABLE_EXISTS_ERROR), table_name);
2620
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2621
ER_TABLE_EXISTS_ERROR,warn_buff);
2023
new_table_message.set_type(message::Table::STANDARD);
2028
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2031
{ // We now do a selective copy of elements on to the new table.
2032
new_table_message.set_name(create_table_proto.name());
2033
new_table_message.set_schema(create_table_proto.schema());
2034
new_table_message.set_catalog(create_table_proto.catalog());
2037
/* Fix names of foreign keys being added */
2038
for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2040
if (new_table_message.fk_constraint(j).has_name())
2042
std::string name(new_table_message.name());
2045
name.append("_ibfk_");
2046
snprintf(number, sizeof(number), "%d", j+1);
2047
name.append(number);
2049
message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
pfkey->set_name(name);
2055
As mysql_truncate don't work on a new table at this stage of
2056
creation, instead create the table directly (for both normal and temporary tables).
2058
bool success= plugin::StorageEngine::createTable(session,
2059
destination_identifier,
2062
if (success && not destination_identifier.isTmp())
2064
TransactionServices &transaction_services= TransactionServices::singleton();
2065
transaction_services.createTable(session, new_table_message);
2072
Create a table identical to the specified table
2076
session Thread object
2077
table Table list element for target table
2078
src_table Table list element for source table
2079
create_info Create info
2086
bool create_like_table(Session* session,
2087
identifier::Table::const_reference destination_identifier,
2088
identifier::Table::const_reference source_identifier,
2089
message::Table &create_table_proto,
2090
bool is_if_not_exists,
2094
bool table_exists= false;
2097
Check that destination tables does not exist. Note that its name
2098
was already checked when it was added to the table list.
2100
For temporary tables we don't aim to grab locks.
2102
if (destination_identifier.isTmp())
2104
if (session->find_temporary_table(destination_identifier))
2110
bool was_created= create_table_wrapper(*session,
2112
destination_identifier,
2115
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2117
(void) session->rm_temporary_table(destination_identifier, true);
2119
else if (not session->open_temporary_table(destination_identifier))
2121
// We created, but we can't open... also, a hack.
2122
(void) session->rm_temporary_table(destination_identifier, true);
2130
else // Standard table which will require locks.
2132
Table *name_lock= 0;
2134
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2138
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
session->unlink_open_table(name_lock);
2149
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2153
else // Otherwise we create the table
2157
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
source_identifier, is_engine_set);
2162
// So we blew the creation of the table, and we scramble to clean up
2163
// anything that might have been created (read... it is a hack)
2164
if (not was_created)
2166
plugin::StorageEngine::dropTable(*session, destination_identifier);
2176
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2177
session->unlink_open_table(name_lock);
2183
if (is_if_not_exists)
2185
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
snprintf(warn_buff, sizeof(warn_buff),
2187
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2188
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
ER_TABLE_EXISTS_ERROR, warn_buff);
2193
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2202
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2625
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2630
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2631
session->unlink_open_table(name_lock);
2632
pthread_mutex_unlock(&LOCK_open);
2638
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2204
2640
thr_lock_type lock_type = TL_READ_NO_INSERT;
2206
return(admin_table(session, tables, check_opt,
2207
"analyze", lock_type, true,
2642
return(mysql_admin_table(session, tables, check_opt,
2643
"analyze", lock_type, 1, 0, 0, 0,
2208
2644
&Cursor::ha_analyze));
2212
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2648
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2214
2650
thr_lock_type lock_type = TL_READ_NO_INSERT;
2216
return(admin_table(session, tables, check_opt,
2652
return(mysql_admin_table(session, tables, check_opt,
2217
2653
"check", lock_type,
2654
0, 0, HA_OPEN_FOR_REPAIR, 0,
2219
2655
&Cursor::ha_check));
2222
} /* namespace drizzled */
2659
Recreates tables by calling drizzled::alter_table().
2662
mysql_recreate_table()
2663
session Thread Cursor
2664
tables Tables to recreate
2667
Like drizzled::alter_table().
2669
bool mysql_recreate_table(Session *session, TableList *table_list)
2671
HA_CREATE_INFO create_info;
2672
AlterInfo alter_info;
2673
message::Table table_proto;
2675
assert(!table_list->next_global);
2677
table_list->table has been closed and freed. Do not reference
2678
uninitialized data. open_tables() could fail.
2680
table_list->table= NULL;
2682
memset(&create_info, 0, sizeof(create_info));
2683
create_info.row_type=ROW_TYPE_NOT_USED;
2684
create_info.default_table_charset=default_charset_info;
2685
/* Force alter table to recreate table */
2686
alter_info.flags.set(ALTER_CHANGE_COLUMN);
2687
alter_info.flags.set(ALTER_RECREATE);
2688
return(alter_table(session, NULL, NULL, &create_info, &table_proto,
2689
table_list, &alter_info, 0,
2690
(order_st *) 0, 0));
2694
bool mysql_checksum_table(Session *session, TableList *tables,
2695
HA_CHECK_OPT *check_opt)
2698
List<Item> field_list;
2701
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2702
item->maybe_null= 1;
2703
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2704
MY_INT64_NUM_DECIMAL_DIGITS));
2705
item->maybe_null= 1;
2706
if (session->client->sendFields(&field_list))
2709
/* Open one table after the other to keep lock time as short as possible. */
2710
for (table= tables; table; table= table->next_local)
2712
char table_name[NAME_LEN*2+2];
2715
sprintf(table_name,"%s.%s",table->db,table->table_name);
2717
t= table->table= session->openTableLock(table, TL_READ);
2718
session->clear_error(); // these errors shouldn't get client
2720
session->client->store(table_name);
2724
/* Table didn't exist */
2725
session->client->store();
2726
session->clear_error();
2730
if (t->cursor->ha_table_flags() & HA_HAS_CHECKSUM &&
2731
!(check_opt->flags & T_EXTEND))
2732
session->client->store((uint64_t)t->cursor->checksum());
2733
else if (!(t->cursor->ha_table_flags() & HA_HAS_CHECKSUM) &&
2734
(check_opt->flags & T_QUICK))
2735
session->client->store();
2738
/* calculating table's checksum */
2740
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2742
t->use_all_columns();
2744
if (t->cursor->ha_rnd_init(1))
2745
session->client->store();
2750
ha_checksum row_crc= 0;
2751
int error= t->cursor->rnd_next(t->record[0]);
2752
if (unlikely(error))
2754
if (error == HA_ERR_RECORD_DELETED)
2758
if (t->s->null_bytes)
2760
/* fix undefined null bits */
2761
t->record[0][t->s->null_bytes-1] |= null_mask;
2762
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2763
t->record[0][0] |= 1;
2765
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2768
for (uint32_t i= 0; i < t->s->fields; i++ )
2770
Field *f= t->field[i];
2771
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2772
(f->type() == DRIZZLE_TYPE_VARCHAR))
2776
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2779
row_crc= my_checksum(row_crc, f->ptr,
2785
session->client->store((uint64_t)crc);
2786
t->cursor->ha_rnd_end();
2789
session->clear_error();
2790
session->close_thread_tables();
2791
table->table=0; // For query cache
2793
if (session->client->flush())
2801
session->close_thread_tables(); // Shouldn't be needed
2807
bool check_engine(Session *session, const char *table_name,
2808
HA_CREATE_INFO *create_info)
2810
plugin::StorageEngine **new_engine= &create_info->db_type;
2811
plugin::StorageEngine *req_engine= *new_engine;
2812
if (!req_engine->is_enabled())
2814
string engine_name= req_engine->getName();
2815
my_error(ER_FEATURE_DISABLED,MYF(0),
2816
engine_name.c_str(), engine_name.c_str());
2821
if (req_engine && req_engine != *new_engine)
2823
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2824
ER_WARN_USING_OTHER_HANDLER,
2825
ER(ER_WARN_USING_OTHER_HANDLER),
2826
plugin::StorageEngine::resolveName(*new_engine).c_str(),
2829
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
2830
(*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
2832
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
2834
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2835
plugin::StorageEngine::resolveName(*new_engine).c_str(),
2840
*new_engine= myisam_engine;
2842
if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
2843
&& (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
2845
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2846
plugin::StorageEngine::resolveName(*new_engine).c_str(),