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 file 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 file name (WL #1324).
131
tablename_to_filename()
134
to_length The size of the file 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 file: 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 file 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 file: 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 file 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());
97
316
session Thread object
317
clear_error is clear_error to be called
98
318
query Query to log
99
319
query_length Length of query
139
422
-1 Thread was killed
142
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
425
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
426
bool drop_temporary, bool dont_log_query)
145
428
TableList *table;
429
char path[FN_REFLEN];
430
uint32_t path_length= 0;
146
431
String wrong_tables;
148
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
433
int non_temp_tables_count= 0;
434
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
439
built_query.set_charset(system_charset_info);
441
built_query.append("DROP Table IF EXISTS ");
443
built_query.append("DROP Table ");
446
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
449
If we have the table in the definition cache, we don't have to check the
450
.frm file to find if the table is a normal table (not view) and what
454
for (table= tables; table; table= table->next_local)
457
table->db_type= NULL;
458
if ((share= TableShare::getShare(table->db, table->table_name)))
459
table->db_type= share->db_type();
462
if (!drop_temporary && lock_table_names_exclusively(session, tables))
464
pthread_mutex_unlock(&LOCK_open);
468
/* Don't give warnings for not found errors, as we already generate notes */
469
session->no_warnings_for_error= 1;
471
for (table= tables; table; table= table->next_local)
474
plugin::StorageEngine *table_type;
476
error= session->drop_temporary_table(table);
480
// removed temporary table
481
tmp_table_deleted= 1;
485
goto err_with_placeholders;
487
// temporary table not found
492
If row-based replication is used and the table is not a
493
temporary table, we add the table name to the drop statement
494
being built. The string always end in a comma and the comma
495
will be chopped off before being written to the binary log.
499
non_temp_tables_count++;
501
Don't write the database name if it is the current one (or if
502
session->db is NULL).
504
built_query.append("`");
505
if (session->db == NULL || strcmp(db,session->db) != 0)
507
built_query.append(db);
508
built_query.append("`.`");
511
built_query.append(table->table_name);
512
built_query.append("`,");
515
table_type= table->db_type;
519
abort_locked_tables(session, db, table->table_name);
520
remove_table_from_cache(session, db, table->table_name,
521
RTFC_WAIT_OTHER_THREAD_FLAG |
522
RTFC_CHECK_KILLED_FLAG);
524
If the table was used in lock tables, remember it so that
525
unlock_table_names can free it
527
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
528
table->table= locked_table;
533
goto err_with_placeholders;
535
/* remove .frm file and engine files */
536
path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
538
plugin::Registry &plugins= plugin::Registry::singleton();
539
if (drop_temporary ||
541
&& (plugins.storage_engine.getTableProto(path, NULL) != EEXIST))))
543
// Table was not found on disk and table can't be created from engine
545
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
546
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();
553
error= ha_delete_table(session, path, db, table->table_name,
555
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
559
session->clear_error();
561
if (error == HA_ERR_ROW_IS_REFERENCED)
563
/* the table is referenced by a foreign key constraint */
568
some_tables_deleted=1;
573
if (wrong_tables.length())
574
wrong_tables.append(',');
575
wrong_tables.append(String(table->table_name,system_charset_info));
579
It's safe to unlock LOCK_open: we have an exclusive lock
582
pthread_mutex_unlock(&LOCK_open);
253
584
if (wrong_tables.length())
255
if (not foreign_key_error)
586
if (!foreign_key_error)
257
587
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
588
wrong_tables.c_ptr());
262
591
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,
1667
bool mysql_create_table_no_lock(Session *session,
1668
const char *db, const char *table_name,
1431
1669
HA_CREATE_INFO *create_info,
1432
message::Table &table_proto,
1670
message::Table *table_proto,
1433
1671
AlterInfo *alter_info,
1434
1672
bool internal_tmp_table,
1435
uint32_t select_field_count,
1436
bool is_if_not_exists)
1673
uint32_t select_field_count)
1675
char path[FN_REFLEN];
1676
uint32_t path_length;
1438
1677
uint db_options, key_count;
1439
KeyInfo *key_info_buffer;
1678
KEY *key_info_buffer;
1440
1680
bool error= true;
1442
1681
/* Check for duplicate fields and check type of table to create */
1443
if (not alter_info->create_list.elements)
1682
if (!alter_info->create_list.elements)
1445
1684
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1449
assert(identifier.getTableName() == table_proto.name());
1688
assert(strcmp(table_name,table_proto->name().c_str())==0);
1689
if (check_engine(session, table_name, create_info))
1450
1691
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,
1692
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1693
db_options|=HA_OPTION_PACK_RECORD;
1694
if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
1695
create_info->db_type)))
1697
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1701
set_table_default_charset(create_info, (char*) db);
1703
if (mysql_prepare_create_table(session, create_info, alter_info,
1706
&key_info_buffer, &key_count,
1707
select_field_count))
1710
/* Check if table exists */
1711
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1713
path_length= build_tmptable_filename(session, path, sizeof(path));
1718
/* check if the table name contains FN_DEVCHAR when defined */
1719
if (strchr(table_name, FN_DEVCHAR))
1721
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
1725
path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
1728
/* Check if table already exists */
1729
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1730
session->find_temporary_table(db, table_name))
1732
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1734
create_info->table_existed= 1; // Mark that table existed
1735
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1736
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1741
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1745
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1746
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1748
plugin::Registry &plugins= plugin::Registry::singleton();
1749
if (plugins.storage_engine.getTableProto(path, NULL)==EEXIST)
1751
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1754
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1755
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1757
create_info->table_existed= 1; // Mark that table existed
1760
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1762
goto unlock_and_end;
1765
We don't assert here, but check the result, because the table could be
1766
in the table definition cache and in the same time the .frm could be
1767
missing from the disk, in case of manual intervention which deletes
1768
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1769
Then she could create the table. This case is pretty obscure and
1770
therefore we don't introduce a new error message only for it.
1772
if (TableShare::getShare(db, table_name))
1774
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1775
goto unlock_and_end;
1780
Check that table with given name does not already
1781
exist in any storage engine. In such a case it should
1782
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1783
unless user specified CREATE TABLE IF EXISTS
1784
The LOCK_open mutex has been locked to make sure no
1785
one else is attempting to discover the table. Since
1786
it's not on disk as a frm file, no one could be using it!
1788
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1790
bool create_if_not_exists =
1791
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1793
char table_path[FN_REFLEN];
1794
uint32_t table_path_length;
1796
table_path_length= build_table_filename(table_path, sizeof(table_path),
1797
db, table_name, false);
1799
plugin::Registry &plugins= plugin::Registry::singleton();
1800
int retcode= plugins.storage_engine.getTableProto(table_path, NULL);
1804
/* Normal case, no table exists. we can go and create it */
1807
if (create_if_not_exists)
1810
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1811
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1813
create_info->table_existed= 1; // Mark that table existed
1814
goto unlock_and_end;
1816
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1817
goto unlock_and_end;
1819
my_error(retcode, MYF(0),table_name);
1820
goto unlock_and_end;
1824
session->set_proc_info("creating table");
1825
create_info->table_existed= 0; // Mark that table is created
1827
create_info->table_options=db_options;
1829
if (rea_create_table(session, path, db, table_name,
1831
create_info, alter_info->create_list,
1832
key_count, key_info_buffer))
1833
goto unlock_and_end;
1835
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1837
/* Open table and put in temporary table list */
1838
if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
1840
(void) session->rm_temporary_table(create_info->db_type, path);
1841
goto unlock_and_end;
1846
Don't write statement if:
1847
- It is an internal temporary table,
1848
- Row-based logging is used and it we are creating a temporary table, or
1849
- The binary log is not open.
1850
Otherwise, the statement shall be binlogged.
1852
if (!internal_tmp_table &&
1853
((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1854
write_bin_log(session, true, session->query, session->query_length);
1857
pthread_mutex_unlock(&LOCK_open);
1473
1860
session->set_proc_info("After create");
1479
@note the following two methods implement create [temporary] table.
1867
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)
1870
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1871
HA_CREATE_INFO *create_info,
1872
message::Table *table_proto,
1873
AlterInfo *alter_info,
1874
bool internal_tmp_table,
1875
uint32_t select_field_count)
1490
1877
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);
1880
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1882
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
1515
result= create_table_no_lock(session,
1887
if (name_lock == NULL)
1889
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1891
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1892
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1894
create_info->table_existed= 1;
1899
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1906
result= mysql_create_table_no_lock(session, db, table_name, create_info,
1910
select_field_count);
1527
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1915
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1528
1916
session->unlink_open_table(name_lock);
1917
pthread_mutex_unlock(&LOCK_open);
1531
1920
return(result);
1888
2279
char buf[ERRMSGSIZE+20];
1889
2280
uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
2281
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
session->getClient()->store(STRING_WITH_LEN("note"));
1892
session->getClient()->store(buf, length);
2282
session->client->store(STRING_WITH_LEN("note"));
2283
session->client->store(buf, length);
1896
2287
case HA_ADMIN_OK:
1897
session->getClient()->store(STRING_WITH_LEN("status"));
1898
session->getClient()->store(STRING_WITH_LEN("OK"));
2288
session->client->store(STRING_WITH_LEN("status"));
2289
session->client->store(STRING_WITH_LEN("OK"));
1901
2292
case HA_ADMIN_FAILED:
1902
session->getClient()->store(STRING_WITH_LEN("status"));
1903
session->getClient()->store(STRING_WITH_LEN("Operation failed"));
2293
session->client->store(STRING_WITH_LEN("status"));
2294
session->client->store(STRING_WITH_LEN("Operation failed"));
1906
2297
case HA_ADMIN_REJECT:
1907
session->getClient()->store(STRING_WITH_LEN("status"));
1908
session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
2298
session->client->store(STRING_WITH_LEN("status"));
2299
session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
2300
open_for_modify= false;
1912
2303
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"));
2304
session->client->store(STRING_WITH_LEN("status"));
2305
session->client->store(STRING_WITH_LEN("Table is already up to date"));
1917
2308
case HA_ADMIN_CORRUPT:
1918
session->getClient()->store(STRING_WITH_LEN("error"));
1919
session->getClient()->store(STRING_WITH_LEN("Corrupt"));
2309
session->client->store(STRING_WITH_LEN("error"));
2310
session->client->store(STRING_WITH_LEN("Corrupt"));
1923
2314
case HA_ADMIN_INVALID:
1924
session->getClient()->store(STRING_WITH_LEN("error"));
1925
session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
2315
session->client->store(STRING_WITH_LEN("error"));
2316
session->client->store(STRING_WITH_LEN("Invalid argument"));
2319
case HA_ADMIN_TRY_ALTER:
2322
This is currently used only by InnoDB. ha_innobase::optimize() answers
2323
"try with alter", so here we close the table, do an ALTER Table,
2324
reopen the table and do ha_innobase::analyze() on it.
2326
ha_autocommit_or_rollback(session, 0);
2327
session->close_thread_tables();
2328
TableList *save_next_local= table->next_local,
2329
*save_next_global= table->next_global;
2330
table->next_local= table->next_global= 0;
2331
result_code= mysql_recreate_table(session, table);
2333
mysql_recreate_table() can push OK or ERROR.
2334
Clear 'OK' status. If there is an error, keep it:
2335
we will store the error message in a result set row
2338
if (session->main_da.is_ok())
2339
session->main_da.reset_diagnostics_area();
2340
ha_autocommit_or_rollback(session, 0);
2341
session->close_thread_tables();
2342
if (!result_code) // recreation went ok
2344
if ((table->table= session->openTableLock(table, lock_type)) &&
2345
((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
2346
result_code= 0; // analyze went ok
2348
if (result_code) // either mysql_recreate_table or analyze failed
2350
assert(session->is_error());
2351
if (session->is_error())
2353
const char *err_msg= session->main_da.message();
2354
/* Hijack the row already in-progress. */
2355
session->client->store(STRING_WITH_LEN("error"));
2356
session->client->store(err_msg);
2357
(void)session->client->flush();
2358
/* Start off another row for HA_ADMIN_FAILED */
2359
session->client->store(table_name);
2360
session->client->store(operator_name);
2361
session->clear_error();
2364
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
2365
table->next_local= save_next_local;
2366
table->next_global= save_next_global;
2367
goto send_result_message;
2369
case HA_ADMIN_NEEDS_UPGRADE:
2370
case HA_ADMIN_NEEDS_ALTER:
2372
char buf[ERRMSGSIZE];
2375
session->client->store(STRING_WITH_LEN("error"));
2376
length=snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name);
2377
session->client->store(buf, length);
1928
2382
default: // Probably HA_ADMIN_INTERNAL_ERROR
1981
Create a new table by copying from source table
1983
Altough exclusive name-lock on target table protects us from concurrent
1984
DML and DDL operations on it we still want to wrap .FRM creation and call
1985
to plugin::StorageEngine::createTable() in critical section protected by
1986
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1987
disregard name-locks, like I_S implementation, for example. This is a
1988
temporary and should not be copied. Instead we should fix our code to
1989
always honor name-locks.
1991
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1992
during the call to plugin::StorageEngine::createTable().
1993
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,
2431
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
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);
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);
2433
return(mysql_admin_table(session, tables, check_opt,
2434
"optimize", TL_WRITE, 1,0,0,0,
2435
&handler::ha_optimize));
2072
2439
Create a table identical to the specified table
2442
mysql_create_like_table()
2076
2443
session Thread object
2077
2444
table Table list element for target table
2078
2445
src_table Table list element for source table
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,
2453
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2454
HA_CREATE_INFO *create_info)
2456
Table *name_lock= 0;
2457
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2458
uint32_t dst_path_length;
2459
char *db= table->db;
2460
char *table_name= table->table_name;
2093
2462
bool res= true;
2094
bool table_exists= false;
2464
message::Table src_proto;
2466
plugin::Registry &plugins= plugin::Registry::singleton();
2469
By opening source table we guarantee that it exists and no concurrent
2470
DDL operation will mess with it. Later we also take an exclusive
2471
name-lock on target table name, which makes copying of .frm file,
2472
call to ha_create_table() and binlogging atomic against concurrent DML
2473
and DDL operations on target table. Thus by holding both these "locks"
2474
we ensure that our statement is properly isolated from all concurrent
2475
operations which matter.
2477
if (session->open_tables_from_list(&src_table, ¬_used))
2480
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2097
2483
Check that destination tables does not exist. Note that its name
2098
2484
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))
2486
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2488
if (session->find_temporary_table(db, table_name))
2490
dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2494
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2498
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2499
db, table_name, false);
2500
if (plugins.storage_engine.getTableProto(dst_path, NULL) == EEXIST)
2505
Create a new table by copying from source table
2507
Altough exclusive name-lock on target table protects us from concurrent
2508
DML and DDL operations on it we still want to wrap .FRM creation and call
2509
to ha_create_table() in critical section protected by LOCK_open in order
2510
to provide minimal atomicity against operations which disregard name-locks,
2511
like I_S implementation, for example. This is a temporary and should not
2512
be copied. Instead we should fix our code to always honor name-locks.
2514
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2515
during the call to ha_create_table(). See bug #28614 for more info.
2517
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2520
int protoerr= EEXIST;
2522
if (src_table->schema_table)
2524
if (mysql_create_like_schema_frm(session, src_table, create_info,
2527
pthread_mutex_unlock(&LOCK_open);
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)
2204
thr_lock_type lock_type = TL_READ_NO_INSERT;
2206
return(admin_table(session, tables, check_opt,
2207
"analyze", lock_type, true,
2208
&Cursor::ha_analyze));
2212
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2214
thr_lock_type lock_type = TL_READ_NO_INSERT;
2216
return(admin_table(session, tables, check_opt,
2533
protoerr= plugins.storage_engine.getTableProto(src_path, &src_proto);
2536
string dst_proto_path(dst_path);
2537
string file_ext = ".dfe";
2539
dst_proto_path.append(file_ext);
2541
if (protoerr == EEXIST)
2543
plugin::StorageEngine* engine= ha_resolve_by_name(session,
2544
src_proto.engine().name());
2546
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2547
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &src_proto);
2554
if (my_errno == ENOENT)
2555
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2557
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2558
pthread_mutex_unlock(&LOCK_open);
2564
As mysql_truncate don't work on a new table at this stage of
2565
creation, instead create the table directly (for both normal
2566
and temporary tables).
2569
err= ha_create_table(session, dst_path, db, table_name, create_info, 1,
2571
pthread_mutex_unlock(&LOCK_open);
2573
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2575
if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
2577
(void) session->rm_temporary_table(create_info->db_type, dst_path);
2583
(void) quick_rm_table(create_info->db_type, db,
2589
We have to write the query before we unlock the tables.
2593
Since temporary tables are not replicated under row-based
2594
replication, CREATE TABLE ... LIKE ... needs special
2595
treatement. We have four cases to consider, according to the
2596
following decision table:
2598
==== ========= ========= ==============================
2599
Case Target Source Write to binary log
2600
==== ========= ========= ==============================
2601
1 normal normal Original statement
2602
2 normal temporary Generated statement
2603
3 temporary normal Nothing
2604
4 temporary temporary Nothing
2605
==== ========= ========= ==============================
2607
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2609
if (src_table->table->s->tmp_table) // Case 2
2612
String query(buf, sizeof(buf), system_charset_info);
2613
query.length(0); // Have to zero it since constructor doesn't
2617
Here we open the destination table, on which we already have
2618
name-lock. This is needed for store_create_info() to work.
2619
The table will be closed by unlink_open_table() at the end
2622
table->table= name_lock;
2623
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2624
if (session->reopen_name_locked_table(table, false))
2626
pthread_mutex_unlock(&LOCK_open);
2629
pthread_mutex_unlock(&LOCK_open);
2631
int result= store_create_info(table, &query, create_info);
2633
assert(result == 0); // store_create_info() always return 0
2634
write_bin_log(session, true, query.ptr(), query.length());
2637
write_bin_log(session, true, session->query, session->query_length);
2645
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2647
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2648
snprintf(warn_buff, sizeof(warn_buff),
2649
ER(ER_TABLE_EXISTS_ERROR), table_name);
2650
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2651
ER_TABLE_EXISTS_ERROR,warn_buff);
2655
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2660
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2661
session->unlink_open_table(name_lock);
2662
pthread_mutex_unlock(&LOCK_open);
2668
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2670
thr_lock_type lock_type = TL_READ_NO_INSERT;
2672
return(mysql_admin_table(session, tables, check_opt,
2673
"analyze", lock_type, 1, 0, 0, 0,
2674
&handler::ha_analyze));
2678
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2680
thr_lock_type lock_type = TL_READ_NO_INSERT;
2682
return(mysql_admin_table(session, tables, check_opt,
2217
2683
"check", lock_type,
2219
&Cursor::ha_check));
2222
} /* namespace drizzled */
2684
0, 0, HA_OPEN_FOR_REPAIR, 0,
2685
&handler::ha_check));
2689
Recreates tables by calling mysql_alter_table().
2692
mysql_recreate_table()
2693
session Thread handler
2694
tables Tables to recreate
2697
Like mysql_alter_table().
2699
bool mysql_recreate_table(Session *session, TableList *table_list)
2701
HA_CREATE_INFO create_info;
2702
AlterInfo alter_info;
2703
message::Table table_proto;
2705
assert(!table_list->next_global);
2707
table_list->table has been closed and freed. Do not reference
2708
uninitialized data. open_tables() could fail.
2710
table_list->table= NULL;
2712
memset(&create_info, 0, sizeof(create_info));
2713
create_info.row_type=ROW_TYPE_NOT_USED;
2714
create_info.default_table_charset=default_charset_info;
2715
/* Force alter table to recreate table */
2716
alter_info.flags.set(ALTER_CHANGE_COLUMN);
2717
alter_info.flags.set(ALTER_RECREATE);
2718
return(mysql_alter_table(session, NULL, NULL, &create_info, &table_proto,
2719
table_list, &alter_info, 0,
2720
(order_st *) 0, 0));
2724
bool mysql_checksum_table(Session *session, TableList *tables,
2725
HA_CHECK_OPT *check_opt)
2728
List<Item> field_list;
2731
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2732
item->maybe_null= 1;
2733
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2734
MY_INT64_NUM_DECIMAL_DIGITS));
2735
item->maybe_null= 1;
2736
if (session->client->sendFields(&field_list))
2739
/* Open one table after the other to keep lock time as short as possible. */
2740
for (table= tables; table; table= table->next_local)
2742
char table_name[NAME_LEN*2+2];
2745
sprintf(table_name,"%s.%s",table->db,table->table_name);
2747
t= table->table= session->openTableLock(table, TL_READ);
2748
session->clear_error(); // these errors shouldn't get client
2750
session->client->store(table_name);
2754
/* Table didn't exist */
2755
session->client->store();
2756
session->clear_error();
2760
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
2761
!(check_opt->flags & T_EXTEND))
2762
session->client->store((uint64_t)t->file->checksum());
2763
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
2764
(check_opt->flags & T_QUICK))
2765
session->client->store();
2768
/* calculating table's checksum */
2770
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2772
t->use_all_columns();
2774
if (t->file->ha_rnd_init(1))
2775
session->client->store();
2780
ha_checksum row_crc= 0;
2781
int error= t->file->rnd_next(t->record[0]);
2782
if (unlikely(error))
2784
if (error == HA_ERR_RECORD_DELETED)
2788
if (t->s->null_bytes)
2790
/* fix undefined null bits */
2791
t->record[0][t->s->null_bytes-1] |= null_mask;
2792
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2793
t->record[0][0] |= 1;
2795
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2798
for (uint32_t i= 0; i < t->s->fields; i++ )
2800
Field *f= t->field[i];
2801
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2802
(f->type() == DRIZZLE_TYPE_VARCHAR))
2806
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2809
row_crc= my_checksum(row_crc, f->ptr,
2815
session->client->store((uint64_t)crc);
2816
t->file->ha_rnd_end();
2819
session->clear_error();
2820
session->close_thread_tables();
2821
table->table=0; // For query cache
2823
if (session->client->flush())
2831
session->close_thread_tables(); // Shouldn't be needed
2837
bool check_engine(Session *session, const char *table_name,
2838
HA_CREATE_INFO *create_info)
2840
plugin::StorageEngine **new_engine= &create_info->db_type;
2841
plugin::StorageEngine *req_engine= *new_engine;
2842
if (!req_engine->is_enabled())
2844
string engine_name= req_engine->getName();
2845
my_error(ER_FEATURE_DISABLED,MYF(0),
2846
engine_name.c_str(), engine_name.c_str());
2851
if (req_engine && req_engine != *new_engine)
2853
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2854
ER_WARN_USING_OTHER_HANDLER,
2855
ER(ER_WARN_USING_OTHER_HANDLER),
2856
ha_resolve_storage_engine_name(*new_engine).c_str(),
2859
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
2860
(*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
2862
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
2864
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2865
ha_resolve_storage_engine_name(*new_engine).c_str(),
2870
*new_engine= myisam_engine;
2872
if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
2873
&& (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
2875
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
2876
ha_resolve_storage_engine_name(*new_engine).c_str(),