86
82
let's fetch the database default character set and
87
83
apply it to the table.
89
identifier::Schema identifier(db);
90
85
if (create_info->default_table_charset == NULL)
91
create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
86
create_info->default_table_charset= get_default_db_collation(db);
90
Translate a cursor name to a table name (WL #1324).
93
filename_to_tablename()
96
to_length The size of the table name buffer.
101
uint32_t filename_to_tablename(const char *from, char *to, uint32_t to_length)
105
if (!memcmp(from, TMP_FILE_PREFIX, TMP_FILE_PREFIX_LENGTH))
107
/* Temporary table name. */
108
length= strlen(strncpy(to, from, to_length));
112
for (; *from && length < to_length; length++, from++)
119
/* We've found an escaped char - skip the @ */
122
/* There will be a two-position hex-char version of the char */
123
for (int x=1; x >= 0; x--)
125
if (*from >= '0' && *from <= '9')
126
to[length] += ((*from++ - '0') << (4 * x));
127
else if (*from >= 'a' && *from <= 'f')
128
to[length] += ((*from++ - 'a' + 10) << (4 * x));
130
/* Backup because we advanced extra in the inner loop */
140
Translate a table name to a cursor name (WL #1324).
143
tablename_to_filename()
145
to OUT The cursor name
146
to_length The size of the cursor name buffer.
149
true if errors happen. false on success.
151
bool tablename_to_filename(const char *from, char *to, size_t to_length)
155
for (; *from && length < to_length; length++, from++)
157
if ((*from >= '0' && *from <= '9') ||
158
(*from >= 'A' && *from <= 'Z') ||
159
(*from >= 'a' && *from <= 'z') ||
160
/* OSX defines an extra set of high-bit and multi-byte characters
161
that cannot be used on the filesystem. Instead of trying to sort
162
those out, we'll just escape encode all high-bit-set chars on OSX.
163
It won't really hurt anything - it'll just make some filenames ugly. */
164
#if !defined(TARGET_OS_OSX)
165
((unsigned char)*from >= 128) ||
175
if (length + 3 >= to_length)
178
/* We need to escape this char in a way that can be reversed */
180
to[length++]= hexchars[(*from >> 4) & 15];
181
to[length]= hexchars[(*from) & 15];
184
if (check_if_legal_tablename(to) &&
185
length + 4 < to_length)
187
memcpy(to + length, "@@@", 4);
195
Creates path to a cursor: drizzle_data_dir/db/table.ext
198
build_table_filename()
199
buff Where to write result
200
This may be the same as table_name.
203
table_name Table name
205
flags FN_FROM_IS_TMP or FN_TO_IS_TMP
206
table_name is temporary, do not change.
210
Uses database and table name, and extension to create
211
a cursor name in drizzle_data_dir. Database and table
212
names are converted from system_charset_info into "fscs".
213
Unless flags indicate a temporary table name.
214
'db' is always converted.
215
'ext' is not converted.
217
The conversion suppression is required for ALTER Table. This
218
statement creates intermediate tables. These are regular
219
(non-temporary) tables with a temporary name. Their path names must
220
be derivable from the table name. So we cannot use
221
build_tmptable_filename() for them.
224
path length on success, 0 on failure
227
size_t build_table_filename(char *buff, size_t bufflen, const char *db, const char *table_name, bool is_tmp)
229
char dbbuff[FN_REFLEN];
230
char tbbuff[FN_REFLEN];
231
bool conversion_error= false;
233
memset(tbbuff, 0, sizeof(tbbuff));
234
if (is_tmp) // FN_FROM_IS_TMP | FN_TO_IS_TMP
235
strncpy(tbbuff, table_name, sizeof(tbbuff));
238
conversion_error= tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
239
if (conversion_error)
241
errmsg_printf(ERRMSG_LVL_ERROR,
242
_("Table name cannot be encoded and fit within filesystem "
243
"name length restrictions."));
247
memset(dbbuff, 0, sizeof(dbbuff));
248
conversion_error= tablename_to_filename(db, dbbuff, sizeof(dbbuff));
249
if (conversion_error)
251
errmsg_printf(ERRMSG_LVL_ERROR,
252
_("Schema name cannot be encoded and fit within filesystem "
253
"name length restrictions."));
258
int rootdir_len= strlen(FN_ROOTDIR);
259
string table_path(drizzle_data_home);
260
int without_rootdir= table_path.length()-rootdir_len;
262
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
263
if (without_rootdir >= 0)
265
const char *tmp= table_path.c_str()+without_rootdir;
266
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
267
table_path.append(FN_ROOTDIR);
270
table_path.append(dbbuff);
271
table_path.append(FN_ROOTDIR);
272
table_path.append(tbbuff);
274
if (bufflen < table_path.length())
277
strcpy(buff, table_path.c_str());
279
return table_path.length();
284
Creates path to a cursor: drizzle_tmpdir/#sql1234_12_1.ext
287
build_tmptable_filename()
288
session The thread handle.
289
buff Where to write result
294
Uses current_pid, thread_id, and tmp_table counter to create
295
a cursor name in drizzle_tmpdir.
298
path length on success, 0 on failure
301
size_t build_tmptable_filename(char *buff, size_t bufflen)
304
ostringstream path_str, post_tmpdir_str;
307
Session *session= current_session;
309
path_str << drizzle_tmpdir;
310
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
311
post_tmpdir_str << session->thread_id << session->tmp_table++;
312
tmp= post_tmpdir_str.str();
314
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
318
if (bufflen < path_str.str().length())
321
length= unpack_filename(buff, path_str.str().c_str());
139
396
-1 Thread was killed
142
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
399
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
145
402
TableList *table;
403
char path[FN_REFLEN];
404
uint32_t path_length= 0;
146
405
String wrong_tables;
148
407
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
409
pthread_mutex_lock(&LOCK_open); /* Part 2 of rm a table */
412
If we have the table in the definition cache, we don't have to check the
413
.frm cursor to find if the table is a normal table (not view) and what
417
for (table= tables; table; table= table->next_local)
420
table->db_type= NULL;
421
if ((share= TableShare::getShare(table->db, table->table_name)))
422
table->db_type= share->db_type();
425
if (!drop_temporary && lock_table_names_exclusively(session, tables))
427
pthread_mutex_unlock(&LOCK_open);
431
/* Don't give warnings for not found errors, as we already generate notes */
432
session->no_warnings_for_error= 1;
434
for (table= tables; table; table= table->next_local)
437
plugin::StorageEngine *table_type;
439
error= session->drop_temporary_table(table);
443
// removed temporary table
447
goto err_with_placeholders;
449
// temporary table not found
453
table_type= table->db_type;
454
if (drop_temporary == false)
457
abort_locked_tables(session, db, table->table_name);
458
remove_table_from_cache(session, db, table->table_name,
459
RTFC_WAIT_OTHER_THREAD_FLAG |
460
RTFC_CHECK_KILLED_FLAG);
462
If the table was used in lock tables, remember it so that
463
unlock_table_names can free it
465
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
466
table->table= locked_table;
471
goto err_with_placeholders;
473
/* remove .frm cursor and engine files */
474
path_length= build_table_filename(path, sizeof(path), db, table->table_name, table->internal_tmp_table);
476
TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
478
if (drop_temporary ||
480
&& (plugin::StorageEngine::getTableDefinition(*session,
481
identifier) != EEXIST))))
483
// Table was not found on disk and table can't be created from engine
485
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
486
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();
493
error= plugin::StorageEngine::dropTable(*session,
497
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
500
session->clear_error();
503
if (error == HA_ERR_ROW_IS_REFERENCED)
505
/* the table is referenced by a foreign key constraint */
506
foreign_key_error= true;
510
if (error == 0 || (if_exists && foreign_key_error == false))
511
write_bin_log_drop_table(session, if_exists, db, table->table_name);
515
if (wrong_tables.length())
516
wrong_tables.append(',');
517
wrong_tables.append(String(table->table_name,system_charset_info));
521
It's safe to unlock LOCK_open: we have an exclusive lock
524
pthread_mutex_unlock(&LOCK_open);
253
526
if (wrong_tables.length())
255
if (not foreign_key_error)
528
if (!foreign_key_error)
257
529
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
530
wrong_tables.c_ptr());
262
533
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,
1551
bool mysql_create_table_no_lock(Session *session,
1552
TableIdentifier &identifier,
1431
1553
HA_CREATE_INFO *create_info,
1432
message::Table &table_proto,
1554
message::Table *table_proto,
1433
1555
AlterInfo *alter_info,
1434
1556
bool internal_tmp_table,
1435
1557
uint32_t select_field_count,
1436
1558
bool is_if_not_exists)
1438
1560
uint db_options, key_count;
1439
KeyInfo *key_info_buffer;
1561
KEY *key_info_buffer;
1440
1563
bool error= true;
1565
bool lex_identified_temp_table=
1566
(table_proto->type() == drizzled::message::Table::TEMPORARY);
1442
1568
/* Check for duplicate fields and check type of table to create */
1443
if (not alter_info->create_list.elements)
1569
if (!alter_info->create_list.elements)
1445
1571
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1449
assert(identifier.getTableName() == table_proto.name());
1575
assert(strcmp(identifier.getTableName(), table_proto->name().c_str())==0);
1450
1576
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,
1473
session->set_proc_info("After create");
1479
@note the following two methods implement create [temporary] table.
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)
1490
Table *name_lock= NULL;
1493
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1497
else if (name_lock == NULL)
1577
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1578
db_options|=HA_OPTION_PACK_RECORD;
1579
if (!(cursor= create_info->db_type->getCursor(share, session->mem_root)))
1581
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(Cursor));
1585
set_table_default_charset(create_info, identifier.getDBName());
1587
/* Check if table exists */
1588
if (mysql_prepare_create_table(session, create_info, table_proto, alter_info,
1590
&db_options, cursor,
1591
&key_info_buffer, &key_count,
1592
select_field_count))
1595
/* Check if table already exists */
1596
if (lex_identified_temp_table &&
1597
session->find_temporary_table(identifier.getDBName(), identifier.getTableName()))
1499
1599
if (is_if_not_exists)
1601
create_info->table_existed= 1; // Mark that table existed
1501
1602
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
1603
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);
1515
result= create_table_no_lock(session,
1527
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1528
session->unlink_open_table(name_lock);
1604
identifier.getTableName());
1608
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1612
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1613
if (!internal_tmp_table && ! lex_identified_temp_table)
1615
if (plugin::StorageEngine::getTableDefinition(*session,
1616
identifier)==EEXIST)
1618
if (is_if_not_exists)
1621
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1622
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1623
identifier.getTableName());
1624
create_info->table_existed= 1; // Mark that table existed
1627
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1629
goto unlock_and_end;
1632
We don't assert here, but check the result, because the table could be
1633
in the table definition cache and in the same time the .frm could be
1634
missing from the disk, in case of manual intervention which deletes
1635
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1636
Then she could create the table. This case is pretty obscure and
1637
therefore we don't introduce a new error message only for it.
1639
if (TableShare::getShare(identifier.getDBName(), identifier.getTableName()))
1641
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1642
goto unlock_and_end;
1647
Check that table with given name does not already
1648
exist in any storage engine. In such a case it should
1649
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1650
unless user specified CREATE TABLE IF EXISTS
1651
The LOCK_open mutex has been locked to make sure no
1652
one else is attempting to discover the table. Since
1653
it's not on disk as a frm cursor, no one could be using it!
1655
if (! lex_identified_temp_table)
1657
int retcode= plugin::StorageEngine::getTableDefinition(*session, identifier);
1662
/* Normal case, no table exists. we can go and create it */
1665
if (is_if_not_exists)
1668
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1669
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1670
identifier.getTableName());
1671
create_info->table_existed= 1; // Mark that table existed
1672
goto unlock_and_end;
1674
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1675
goto unlock_and_end;
1677
my_error(retcode, MYF(0), identifier.getTableName());
1678
goto unlock_and_end;
1682
session->set_proc_info("creating table");
1683
create_info->table_existed= 0; // Mark that table is created
1685
create_info->table_options= db_options;
1687
if (rea_create_table(session, identifier,
1689
create_info, alter_info->create_list,
1690
key_count, key_info_buffer))
1691
goto unlock_and_end;
1693
if (lex_identified_temp_table)
1695
/* Open table and put in temporary table list */
1696
if (!(session->open_temporary_table(identifier)))
1698
(void) session->rm_temporary_table(create_info->db_type, identifier);
1699
goto unlock_and_end;
1704
Don't write statement if:
1705
- It is an internal temporary table,
1706
- Row-based logging is used and it we are creating a temporary table, or
1707
- The binary log is not open.
1708
Otherwise, the statement shall be binlogged.
1710
if (!internal_tmp_table && ! lex_identified_temp_table)
1711
write_bin_log(session, session->query, session->query_length);
1714
pthread_mutex_unlock(&LOCK_open);
1717
session->set_proc_info("After create");
1536
Database locking aware wrapper for create_table_no_lock(),
1724
Database locking aware wrapper for mysql_create_table_no_lock(),
1538
bool create_table(Session *session,
1539
const identifier::Table &identifier,
1727
bool mysql_create_table(Session *session,
1728
TableIdentifier &identifier,
1540
1729
HA_CREATE_INFO *create_info,
1541
message::Table &table_proto,
1730
message::Table *table_proto,
1542
1731
AlterInfo *alter_info,
1543
1732
bool internal_tmp_table,
1544
1733
uint32_t select_field_count,
1545
1734
bool is_if_not_exists)
1547
if (identifier.isTmp())
1549
return create_table_no_lock(session,
1559
return drizzle_create_table(session,
1736
Table *name_lock= NULL;
1738
bool lex_identified_temp_table=
1739
(table_proto->type() == drizzled::message::Table::TEMPORARY);
1741
if (! lex_identified_temp_table)
1743
if (session->lock_table_name_if_not_cached(identifier.getDBName(),
1744
identifier.getTableName(),
1750
if (name_lock == NULL)
1752
if (is_if_not_exists)
1754
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1755
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1756
identifier.getTableName());
1757
create_info->table_existed= 1;
1762
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getTableName());
1769
result= mysql_create_table_no_lock(session,
1781
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1782
session->unlink_open_table(name_lock);
1783
pthread_mutex_unlock(&LOCK_open);
2199
Create a table identical to the specified table
2202
mysql_create_like_table()
2203
session Thread object
2204
table Table list element for target table
2205
src_table Table list element for source table
2206
create_info Create info
2213
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2214
drizzled::message::Table& create_table_proto,
2215
drizzled::plugin::StorageEngine *engine_arg,
2216
bool is_if_not_exists,
2219
Table *name_lock= 0;
2220
char src_path[FN_REFLEN];
2221
char *db= table->db;
2222
char *table_name= table->table_name;
2226
message::Table src_proto;
2227
bool lex_identified_temp_table=
2228
(create_table_proto.type() == drizzled::message::Table::TEMPORARY);
2231
By opening source table we guarantee that it exists and no concurrent
2232
DDL operation will mess with it. Later we also take an exclusive
2233
name-lock on target table name, which makes copying of .frm cursor,
2234
call to plugin::StorageEngine::createTable() and binlogging atomic
2235
against concurrent DML and DDL operations on target table.
2236
Thus by holding both these "locks" we ensure that our statement is
2237
properly isolated from all concurrent operations which matter.
2239
if (session->open_tables_from_list(&src_table, ¬_used))
2242
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2245
TableIdentifier destination_identifier(db, table_name, lex_identified_temp_table ? TEMP_TABLE : NO_TMP_TABLE);
2248
Check that destination tables does not exist. Note that its name
2249
was already checked when it was added to the table list.
2251
if (lex_identified_temp_table)
2253
if (session->find_temporary_table(db, table_name))
2258
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2263
if (plugin::StorageEngine::getTableDefinition(*session,
2264
destination_identifier) == EEXIST)
1981
2269
Create a new table by copying from source table
1983
2271
Altough exclusive name-lock on target table protects us from concurrent
1984
2272
DML and DDL operations on it we still want to wrap .FRM creation and call
1985
2273
to plugin::StorageEngine::createTable() in critical section protected by
1986
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
2274
LOCK_open in order to provide minimal atomicity against operations which
1987
2275
disregard name-locks, like I_S implementation, for example. This is a
1988
2276
temporary and should not be copied. Instead we should fix our code to
1989
2277
always honor name-locks.
1991
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
2279
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
2280
during the call to plugin::StorageEngine::createTable().
1993
2281
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);
2283
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2285
int protoerr= EEXIST;
2288
* If an engine was not specified and we are reading from an I_S table, then we need to toss an
2289
* error. This should go away soon.
2290
* @todo make this go away!
2292
if (! is_engine_set)
2294
string tab_name(src_path);
2295
string i_s_prefix("./information_schema/");
2296
if (tab_name.compare(0, i_s_prefix.length(), i_s_prefix) == 0)
2298
pthread_mutex_unlock(&LOCK_open);
2299
my_error(ER_ILLEGAL_HA_CREATE_OPTION,
2301
"INFORMATION_ENGINE",
2307
protoerr= plugin::StorageEngine::getTableDefinition(*session,
2314
message::Table new_proto(src_proto);
2316
if (lex_identified_temp_table)
2318
new_proto.set_type(message::Table::TEMPORARY);
2322
new_proto.set_type(message::Table::STANDARD);
2327
message::Table::StorageEngine *protoengine;
2329
protoengine= new_proto.mutable_engine();
2330
protoengine->set_name(create_table_proto.engine().name());
2333
if (protoerr == EEXIST)
2335
plugin::StorageEngine* engine= plugin::StorageEngine::findByName(*session,
2336
new_proto.engine().name());
2338
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2340
string dst_proto_path(destination_identifier.getPath());
2341
dst_proto_path.append(".dfe");
2343
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &new_proto);
2353
if (errno == ENOENT)
2354
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2356
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath(), errno);
2357
pthread_mutex_unlock(&LOCK_open);
2362
As mysql_truncate don't work on a new table at this stage of
2363
creation, instead create the table directly (for both normal
2364
and temporary tables).
2366
err= plugin::StorageEngine::createTable(*session,
2367
destination_identifier,
2370
pthread_mutex_unlock(&LOCK_open);
2372
if (lex_identified_temp_table)
2374
if (err || !session->open_temporary_table(destination_identifier))
2376
(void) session->rm_temporary_table(engine_arg, destination_identifier);
2382
TableIdentifier identifier(db, table_name, NO_TMP_TABLE);
2383
quick_rm_table(*session, identifier);
2389
We have to write the query before we unlock the tables.
2393
Since temporary tables are not replicated under row-based
2394
replication, CREATE TABLE ... LIKE ... needs special
2395
treatement. We have four cases to consider, according to the
2396
following decision table:
2398
==== ========= ========= ==============================
2399
Case Target Source Write to binary log
2400
==== ========= ========= ==============================
2401
1 normal normal Original statement
2402
2 normal temporary Generated statement
2403
3 temporary normal Nothing
2404
4 temporary temporary Nothing
2405
==== ========= ========= ==============================
2407
if (! lex_identified_temp_table)
2409
if (src_table->table->s->tmp_table) // Case 2
2412
String query(buf, sizeof(buf), system_charset_info);
2413
query.length(0); // Have to zero it since constructor doesn't
2417
Here we open the destination table, on which we already have
2418
name-lock. This is needed for store_create_info() to work.
2419
The table will be closed by unlink_open_table() at the end
2422
table->table= name_lock;
2423
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2424
if (session->reopen_name_locked_table(table, false))
2426
pthread_mutex_unlock(&LOCK_open);
2429
pthread_mutex_unlock(&LOCK_open);
2431
int result= store_create_info(table, &query, is_if_not_exists);
2433
assert(result == 0); // store_create_info() always return 0
2434
write_bin_log(session, query.ptr(), query.length());
2437
write_bin_log(session, session->query, session->query_length);
2445
if (is_if_not_exists)
2447
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2448
snprintf(warn_buff, sizeof(warn_buff),
2449
ER(ER_TABLE_EXISTS_ERROR), table_name);
2450
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2451
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)
2455
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2460
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2461
session->unlink_open_table(name_lock);
2462
pthread_mutex_unlock(&LOCK_open);
2468
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2204
2470
thr_lock_type lock_type = TL_READ_NO_INSERT;
2206
return(admin_table(session, tables, check_opt,
2472
return(mysql_admin_table(session, tables, check_opt,
2207
2473
"analyze", lock_type, true,
2208
2474
&Cursor::ha_analyze));
2212
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2478
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2214
2480
thr_lock_type lock_type = TL_READ_NO_INSERT;
2216
return(admin_table(session, tables, check_opt,
2482
return(mysql_admin_table(session, tables, check_opt,
2217
2483
"check", lock_type,
2219
2485
&Cursor::ha_check));
2222
} /* namespace drizzled */
2489
bool mysql_checksum_table(Session *session, TableList *tables,
2493
List<Item> field_list;
2496
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
2497
item->maybe_null= 1;
2498
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
2499
MY_INT64_NUM_DECIMAL_DIGITS));
2500
item->maybe_null= 1;
2501
if (session->client->sendFields(&field_list))
2504
/* Open one table after the other to keep lock time as short as possible. */
2505
for (table= tables; table; table= table->next_local)
2507
char table_name[NAME_LEN*2+2];
2510
sprintf(table_name,"%s.%s",table->db,table->table_name);
2512
t= table->table= session->openTableLock(table, TL_READ);
2513
session->clear_error(); // these errors shouldn't get client
2515
session->client->store(table_name);
2519
/* Table didn't exist */
2520
session->client->store();
2521
session->clear_error();
2526
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2528
if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
2530
session->client->store((uint64_t)t->cursor->checksum());
2534
/* calculating table's checksum */
2536
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
2538
t->use_all_columns();
2540
if (t->cursor->ha_rnd_init(1))
2541
session->client->store();
2546
ha_checksum row_crc= 0;
2547
int error= t->cursor->rnd_next(t->record[0]);
2548
if (unlikely(error))
2550
if (error == HA_ERR_RECORD_DELETED)
2554
if (t->s->null_bytes)
2556
/* fix undefined null bits */
2557
t->record[0][t->s->null_bytes-1] |= null_mask;
2558
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
2559
t->record[0][0] |= 1;
2561
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
2564
for (uint32_t i= 0; i < t->s->fields; i++ )
2566
Field *f= t->field[i];
2567
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
2568
(f->type() == DRIZZLE_TYPE_VARCHAR))
2572
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
2575
row_crc= my_checksum(row_crc, f->ptr,
2581
session->client->store((uint64_t)crc);
2582
t->cursor->ha_rnd_end();
2585
session->clear_error();
2586
session->close_thread_tables();
2587
table->table=0; // For query cache
2589
if (session->client->flush())
2597
session->close_thread_tables(); // Shouldn't be needed