summaryrefslogtreecommitdiff
path: root/innobase/row/row0mysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r--innobase/row/row0mysql.c1024
1 files changed, 559 insertions, 465 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 49e5aeac2e4..5432add37f7 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -47,6 +47,51 @@ struct row_mysql_drop_struct{
UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
ibool row_mysql_drop_list_inited = FALSE;
+/* Magic table names for invoking various monitor threads */
+static const char S_innodb_monitor[] = "innodb_monitor";
+static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";
+static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
+static const char S_innodb_table_monitor[] = "innodb_table_monitor";
+static const char S_innodb_mem_validate[] = "innodb_mem_validate";
+
+/* Name suffix for recovered orphaned temporary tables */
+static const char S_recover_innodb_tmp_table[] = "_recover_innodb_tmp_table";
+/***********************************************************************
+Determine if the given name ends in the suffix reserved for recovered
+orphaned temporary tables. */
+static
+ibool
+row_mysql_is_recovered_tmp_table(
+/*=============================*/
+ /* out: TRUE if table name ends in
+ the reserved suffix */
+ const char* name)
+{
+ ulint namelen = strlen(name) + 1;
+ return(namelen >= sizeof S_recover_innodb_tmp_table
+ && !memcmp(name + namelen -
+ sizeof S_recover_innodb_tmp_table,
+ S_recover_innodb_tmp_table,
+ sizeof S_recover_innodb_tmp_table));
+}
+
+/***********************************************************************
+Determine if the given name is a name reserved for MySQL system tables. */
+static
+ibool
+row_mysql_is_system_table(
+/*======================*/
+ /* out: TRUE if name is a MySQL
+ system table name */
+ const char* name)
+{
+ if (memcmp(name, "mysql/", 6)) {
+ return(FALSE);
+ }
+ return(0 == strcmp(name + 6, "host")
+ || 0 == strcmp(name + 6, "user")
+ || 0 == strcmp(name + 6, "db"));
+}
/***********************************************************************
Reads a MySQL format variable-length field (like VARCHAR) length and
returns pointer to the field data. */
@@ -267,22 +312,22 @@ handle_new_error:
} else if (err == DB_MUST_GET_MORE_FILE_SPACE) {
- fprintf(stderr,
+ fputs(
"InnoDB: The database cannot continue operation because of\n"
"InnoDB: lack of space. You must add a new data file to\n"
- "InnoDB: my.cnf and restart the database.\n");
+ "InnoDB: my.cnf and restart the database.\n", stderr);
exit(1);
} else if (err == DB_CORRUPTION) {
- fprintf(stderr,
+ fputs(
"InnoDB: We detected index corruption in an InnoDB type table.\n"
"InnoDB: You have to dump + drop + reimport the table or, in\n"
"InnoDB: a case of widespread corruption, dump all InnoDB\n"
"InnoDB: tables and recreate the whole InnoDB tablespace.\n"
"InnoDB: If the mysqld server crashes after the startup or when\n"
"InnoDB: you dump the tables, look at section 6.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html for help.\n");
+ "InnoDB: http://www.innodb.com/ibman.html for help.\n", stderr);
} else {
fprintf(stderr, "InnoDB: unknown error code %lu\n",
@@ -395,10 +440,11 @@ row_prebuilt_free(
|| prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
-"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name %s\n",
+"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name",
(ulong) prebuilt->magic_n,
- (ulong) prebuilt->magic_n2,
- prebuilt->table->name);
+ (ulong) prebuilt->magic_n2);
+ ut_print_name(stderr, prebuilt->table->name);
+ putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -443,9 +489,9 @@ row_prebuilt_free(
|| (ROW_PREBUILT_FETCH_MAGIC_N !=
mach_read_from_4((prebuilt->fetch_cache[i])
+ prebuilt->mysql_row_len))) {
- fprintf(stderr,
+ fputs(
"InnoDB: Error: trying to free a corrupt\n"
- "InnoDB: fetch buffer.\n");
+ "InnoDB: fetch buffer.\n", stderr);
mem_analyze_corruption(
prebuilt->fetch_cache[i]);
@@ -488,8 +534,10 @@ row_update_prebuilt_trx(
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to use a corrupt\n"
- "InnoDB: table handle. Magic n %lu, table name %s\n",
- (ulong) prebuilt->magic_n, prebuilt->table->name);
+ "InnoDB: table handle. Magic n %lu, table name",
+ (ulong) prebuilt->magic_n);
+ ut_print_name(stderr, prebuilt->table->name);
+ putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -663,10 +711,94 @@ run_again:
/* It may be that the current session has not yet started
its transaction, or it has been committed: */
-
+
+ trx_start_if_not_started(trx);
+
+ err = lock_table(0, prebuilt->table, prebuilt->select_lock_type, thr);
+
+ trx->error_state = err;
+
+ if (err != DB_SUCCESS) {
+ que_thr_stop_for_mysql(thr);
+
+ was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
+
+ if (was_lock_wait) {
+ goto run_again;
+ }
+
+ trx->op_info = (char *) "";
+
+ return(err);
+ }
+
+ que_thr_stop_for_mysql_no_error(thr, trx);
+
+ trx->op_info = (char *) "";
+
+ return((int) err);
+}
+
+/*************************************************************************
+Unlocks a table lock possibly reserved by trx. */
+
+void
+row_unlock_table_for_mysql(
+/*=======================*/
+ trx_t* trx) /* in: transaction */
+{
+ if (!trx->n_tables_locked) {
+
+ return;
+ }
+
+ mutex_enter(&kernel_mutex);
+ lock_release_tables_off_kernel(trx);
+ mutex_exit(&kernel_mutex);
+}
+/*************************************************************************
+Sets a table lock on the table mentioned in prebuilt. */
+
+int
+row_lock_table_for_mysql(
+/*=====================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL
+ table handle */
+{
+ trx_t* trx = prebuilt->trx;
+ que_thr_t* thr;
+ ulint err;
+ ibool was_lock_wait;
+
+ ut_ad(trx);
+ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+
+ trx->op_info = (char *) "setting table lock";
+
+ if (prebuilt->sel_graph == NULL) {
+ /* Build a dummy select query graph */
+ row_prebuild_sel_graph(prebuilt);
+ }
+
+ /* We use the select query graph as the dummy graph needed
+ in the lock module call */
+
+ thr = que_fork_get_first_thr(prebuilt->sel_graph);
+
+ que_thr_move_to_run_state_for_mysql(thr, trx);
+
+run_again:
+ thr->run_node = thr;
+ thr->prev_node = thr->common.parent;
+
+ /* It may be that the current session has not yet started
+ its transaction, or it has been committed: */
+
trx_start_if_not_started(trx);
- err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr);
+ err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
+ prebuilt->select_lock_type, thr);
trx->error_state = err;
@@ -715,8 +847,10 @@ row_insert_for_mysql(
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
- "InnoDB: table handle. Magic n %lu, table name %s\n",
- (ulong) prebuilt->magic_n, prebuilt->table->name);
+ "InnoDB: table handle. Magic n %lu, table name",
+ (ulong) prebuilt->magic_n);
+ ut_print_name(stderr, prebuilt->table->name);
+ putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -724,12 +858,13 @@ row_insert_for_mysql(
}
if (srv_created_new_raw || srv_force_recovery) {
- fprintf(stderr,
+ fputs(
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n");
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
return(DB_ERROR);
}
@@ -919,11 +1054,7 @@ row_update_for_mysql(
upd_node_t* node;
dict_table_t* table = prebuilt->table;
trx_t* trx = prebuilt->trx;
-/* mem_heap_t* heap;
- dtuple_t* search_tuple;
- dtuple_t* row_tuple;
- mtr_t mtr; */
-
+
ut_ad(prebuilt && trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
UT_NOT_USED(mysql_rec);
@@ -931,8 +1062,10 @@ row_update_for_mysql(
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
- "InnoDB: table handle. Magic n %lu, table name %s\n",
- (ulong) prebuilt->magic_n, prebuilt->table->name);
+ "InnoDB: table handle. Magic n %lu, table name",
+ (ulong) prebuilt->magic_n);
+ ut_print_name(stderr, prebuilt->table->name);
+ putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -940,12 +1073,13 @@ row_update_for_mysql(
}
if (srv_created_new_raw || srv_force_recovery) {
- fprintf(stderr,
+ fputs(
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n");
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
return(DB_ERROR);
}
@@ -1166,36 +1300,30 @@ row_mysql_recover_tmp_table(
dict_table_t* table, /* in: table definition */
trx_t* trx) /* in: transaction handle */
{
- char* ptr;
- char old_name[OS_FILE_MAX_PATH];
-
- ut_a(ut_strlen(table->name) + 10 < OS_FILE_MAX_PATH);
+ const char* ptr = strstr(table->name, "/rsql");
- ut_memcpy(old_name, table->name, ut_strlen(table->name) + 1);
-
- ptr = old_name;
-
- for (;;) {
- if (ptr >= old_name + ut_strlen(table->name) - 6) {
- trx_commit_for_mysql(trx);
-
- return(DB_ERROR);
- }
-
- if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) {
- ptr++;
- *ptr = '#';
-
- break;
- }
-
- ptr++;
+ if (!ptr) {
+ /* table name does not begin with "/rsql" */
+ trx_commit_for_mysql(trx);
+ return(DB_ERROR);
+ }
+ else {
+ int status;
+ int namelen = strlen(table->name);
+ char* old_name = mem_strdupl(table->name, namelen);
+ /* replace "rsql" with "#sql" */
+ old_name[ptr - table->name + 1] = '#';
+ /* remove "_recover_innodb_tmp_table" suffix */
+ ut_ad(namelen > (int) sizeof S_recover_innodb_tmp_table);
+ ut_ad(!strcmp(old_name + namelen + 1 -
+ sizeof S_recover_innodb_tmp_table,
+ S_recover_innodb_tmp_table));
+ old_name[namelen + 1 - sizeof S_recover_innodb_tmp_table] = 0;
+ status = row_rename_table_for_mysql(old_name,
+ table->name, trx);
+ mem_free(old_name);
+ return(status);
}
-
- old_name[ut_strlen(table->name)
- - ut_strlen("_recover_innodb_tmp_table")] = '\0';
-
- return(row_rename_table_for_mysql(old_name, table->name, trx));
}
/*************************************************************************
@@ -1270,9 +1398,10 @@ row_mysql_unlock_data_dictionary(
}
/*************************************************************************
-Does a table creation operation for MySQL. If the name of the created
-table ends to characters INNODB_MONITOR, then this also starts
-printing of monitor output by the master thread. */
+Does a table creation operation for MySQL. If the name of the table
+to be created is equal with one of the predefined magic table names,
+then this also starts printing the corresponding monitor output by
+the master thread. */
int
row_create_table_for_mysql(
@@ -1285,7 +1414,6 @@ row_create_table_for_mysql(
mem_heap_t* heap;
que_thr_t* thr;
ulint namelen;
- ulint keywordlen;
ulint err;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -1296,12 +1424,13 @@ row_create_table_for_mysql(
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
if (srv_created_new_raw) {
- fprintf(stderr,
+ fputs(
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n");
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
trx_commit_for_mysql(trx);
@@ -1310,10 +1439,8 @@ row_create_table_for_mysql(
trx->op_info = (char *) "creating table";
- if (0 == ut_strcmp(table->name, (char*)"mysql/host")
- || 0 == ut_strcmp(table->name, (char*)"mysql/user")
- || 0 == ut_strcmp(table->name, (char*)"mysql/db")) {
-
+ if (row_mysql_is_system_table(table->name)) {
+
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
"InnoDB: MySQL system tables must be of the MyISAM type!\n",
@@ -1326,13 +1453,7 @@ row_create_table_for_mysql(
trx_start_if_not_started(trx);
- namelen = ut_strlen(table->name);
-
- keywordlen = ut_strlen("_recover_innodb_tmp_table");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(table->name + namelen - keywordlen,
- (char*)"_recover_innodb_tmp_table", keywordlen)) {
+ if (row_mysql_is_recovered_tmp_table(table->name)) {
/* MySQL prevents accessing of tables whose name begins
with #sql, that is temporary tables. If mysqld crashes in
@@ -1344,15 +1465,13 @@ row_create_table_for_mysql(
return(row_mysql_recover_tmp_table(table, trx));
}
- namelen = ut_strlen(table->name);
-
- keywordlen = ut_strlen((char *) "innodb_monitor");
+ namelen = strlen(table->name) + 1;
- if (namelen >= keywordlen
- && 0 == ut_memcmp(table->name + namelen - keywordlen,
- (char *) "innodb_monitor", keywordlen)) {
+ if (namelen == sizeof S_innodb_monitor
+ && !memcmp(table->name, S_innodb_monitor,
+ sizeof S_innodb_monitor)) {
- /* Table name ends to characters innodb_monitor:
+ /* Table equals "innodb_monitor":
start monitor prints */
srv_print_innodb_monitor = TRUE;
@@ -1361,60 +1480,42 @@ row_create_table_for_mysql(
of InnoDB monitor prints */
os_event_set(srv_lock_timeout_thread_event);
- }
-
- keywordlen = ut_strlen((char *) "innodb_lock_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(table->name + namelen - keywordlen,
- (char *) "innodb_lock_monitor", keywordlen)) {
+ } else if (namelen == sizeof S_innodb_lock_monitor
+ && !memcmp(table->name, S_innodb_lock_monitor,
+ sizeof S_innodb_lock_monitor)) {
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- }
-
- keywordlen = ut_strlen((char *) "innodb_tablespace_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(table->name + namelen - keywordlen,
- (char *) "innodb_tablespace_monitor",
- keywordlen)) {
+ } else if (namelen == sizeof S_innodb_tablespace_monitor
+ && !memcmp(table->name, S_innodb_tablespace_monitor,
+ sizeof S_innodb_tablespace_monitor)) {
srv_print_innodb_tablespace_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- }
-
- keywordlen = ut_strlen((char *) "innodb_table_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(table->name + namelen - keywordlen,
- (char *) "innodb_table_monitor",
- keywordlen)) {
+ } else if (namelen == sizeof S_innodb_table_monitor
+ && !memcmp(table->name, S_innodb_table_monitor,
+ sizeof S_innodb_table_monitor)) {
srv_print_innodb_table_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- }
-
- keywordlen = ut_strlen("innodb_mem_validate");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(table->name + namelen - keywordlen,
- (char*)"innodb_mem_validate", keywordlen)) {
-
+ } else if (namelen == sizeof S_innodb_mem_validate
+ && !memcmp(table->name, S_innodb_mem_validate,
+ sizeof S_innodb_mem_validate)) {
/* We define here a debugging feature intended for
developers */
- printf("Validating InnoDB memory:\n"
+ fputs("Validating InnoDB memory:\n"
"to use this feature you must compile InnoDB with\n"
"UNIV_MEM_DEBUG defined in univ.i and the server must be\n"
"quiet because allocation from a mem heap is not protected\n"
- "by any semaphore.\n");
+ "by any semaphore.\n", stderr);
#ifdef UNIV_MEM_DEBUG
ut_a(mem_validate());
- printf("Memory validated\n");
+ fputs("Memory validated\n", stderr);
#else /* UNIV_MEM_DEBUG */
- puts("Memory NOT validated (recompile with UNIV_MEM_DEBUG)");
+ fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n",
+ stderr);
#endif /* UNIV_MEM_DEBUG */
}
@@ -1439,29 +1540,28 @@ row_create_table_for_mysql(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
if (err == DB_OUT_OF_FILE_SPACE) {
- fprintf(stderr,
- "InnoDB: Warning: cannot create table %s because tablespace full\n",
- table->name);
- row_drop_table_for_mysql(table->name, trx);
+ fputs("InnoDB: Warning: cannot create table ", stderr);
+ ut_print_name(stderr, table->name);
+ fputs(" because tablespace full\n", stderr);
+ row_drop_table_for_mysql(table->name, trx, FALSE);
} else if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: table %s already exists in InnoDB internal\n"
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, table->name);
+ fputs(" already exists in InnoDB internal\n"
"InnoDB: data dictionary. Have you deleted the .frm file\n"
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
"InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n"
- "InnoDB: See the Restrictions section of the InnoDB manual.\n",
- table->name);
- fprintf(stderr,
+ "InnoDB: See the Restrictions section of the InnoDB manual.\n"
"InnoDB: You can drop the orphaned table inside InnoDB by\n"
"InnoDB: creating an InnoDB table with the same name in another\n"
"InnoDB: database and moving the .frm file to the current database.\n"
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
"InnoDB: succeed.\n"
"InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html\n");
+ "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
}
/* We may also get err == DB_ERROR if the .ibd file for the
@@ -1492,8 +1592,6 @@ row_create_index_for_mysql(
ind_node_t* node;
mem_heap_t* heap;
que_thr_t* thr;
- ulint namelen;
- ulint keywordlen;
ulint err;
ulint i, j;
@@ -1517,11 +1615,14 @@ row_create_index_for_mysql(
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: column %s appears twice in index %s of table %s\n"
-"InnoDB: This is not allowed in InnoDB.\n",
- dict_index_get_nth_field(index, i)->name,
- index->name, index->table_name);
+ fputs(" InnoDB: Error: column ", stderr);
+ ut_print_name(stderr,
+ dict_index_get_nth_field(index, i)->name);
+ fputs(" appears twice in ", stderr);
+ dict_index_name_print(stderr, index);
+ fputs("\n"
+ "InnoDB: This is not allowed in InnoDB.\n",
+ stderr);
err = DB_COL_APPEARS_TWICE_IN_INDEX;
@@ -1532,14 +1633,7 @@ row_create_index_for_mysql(
trx_start_if_not_started(trx);
- namelen = ut_strlen(index->table_name);
-
- keywordlen = ut_strlen("_recover_innodb_tmp_table");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(
- index->table_name + namelen - keywordlen,
- (char*)"_recover_innodb_tmp_table", keywordlen)) {
+ if (row_mysql_is_recovered_tmp_table(index->table_name)) {
return(DB_SUCCESS);
}
@@ -1570,7 +1664,7 @@ error_handling:
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(index->table_name, trx);
+ row_drop_table_for_mysql(index->table_name, trx, FALSE);
trx->error_state = DB_SUCCESS;
}
@@ -1602,8 +1696,6 @@ row_table_add_foreign_constraints(
char* name) /* in: table full name in the normalized form
database_name/table_name */
{
- ulint namelen;
- ulint keywordlen;
ulint err;
#ifdef UNIV_SYNC_DEBUG
@@ -1616,14 +1708,7 @@ row_table_add_foreign_constraints(
trx_start_if_not_started(trx);
- namelen = ut_strlen(name);
-
- keywordlen = ut_strlen("_recover_innodb_tmp_table");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(
- name + namelen - keywordlen,
- (char*)"_recover_innodb_tmp_table", keywordlen)) {
+ if (row_mysql_is_recovered_tmp_table(name)) {
return(DB_SUCCESS);
}
@@ -1644,7 +1729,7 @@ row_table_add_foreign_constraints(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(name, trx);
+ row_drop_table_for_mysql(name, trx, FALSE);
trx->error_state = DB_SUCCESS;
}
@@ -1671,16 +1756,19 @@ row_drop_table_for_mysql_in_background(
trx = trx_allocate_for_background();
-/* fprintf(stderr, "InnoDB: Dropping table %s in background drop list\n",
- name); */
+/* fputs("InnoDB: Error: Dropping table ", stderr);
+ ut_print_name(stderr, name);
+ fputs(" in background drop list\n", stderr); */
+
/* Drop the table in InnoDB */
- error = row_drop_table_for_mysql(name, trx);
+ error = row_drop_table_for_mysql(name, trx, FALSE);
if (error != DB_SUCCESS) {
- fprintf(stderr,
- "InnoDB: Error: Dropping table %s in background drop list failed\n",
- name);
+ ut_print_timestamp(stderr);
+ fputs(" InnoDB: Error: Dropping table ", stderr);
+ ut_print_name(stderr, name);
+ fputs(" in background drop list failed\n", stderr);
}
/* Flush the log to reduce probability that the .frm files and
@@ -1758,9 +1846,9 @@ already_dropped:
UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Dropped table %s in background drop queue.\n",
- drop->table_name);
+ fputs(" InnoDB: Dropped table ", stderr);
+ ut_print_name(stderr, drop->table_name);
+ fputs(" in background drop queue.\n", stderr);
mem_free(drop->table_name);
@@ -1807,9 +1895,7 @@ row_add_table_to_background_drop_list(
drop = mem_alloc(sizeof(row_mysql_drop_t));
- drop->table_name = mem_alloc(1 + ut_strlen(table->name));
-
- ut_memcpy(drop->table_name, table->name, 1 + ut_strlen(table->name));
+ drop->table_name = mem_strdup(table->name);
mutex_enter(&kernel_mutex);
@@ -1821,8 +1907,10 @@ row_add_table_to_background_drop_list(
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
-/* fprintf(stderr, "InnoDB: Adding table %s to background drop list\n",
- drop->table_name); */
+/* fputs("InnoDB: Adding table ", stderr);
+ ut_print_name(stderr, drop->table_name);
+ fputs(" to background drop list\n", stderr); */
+
mutex_exit(&kernel_mutex);
}
@@ -2082,16 +2170,17 @@ funct_exit:
}
/*************************************************************************
-Drops a table for MySQL. If the name of the dropped table ends to
-characters INNODB_MONITOR, then this also stops printing of monitor
-output by the master thread. */
+Drops a table for MySQL. If the name of the table to be dropped is equal
+with one of the predefined magic table names, then this also stops printing
+the corresponding monitor output by the master thread. */
int
row_drop_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
- trx_t* trx) /* in: transaction handle */
+ trx_t* trx, /* in: transaction handle */
+ ibool drop_db)/* in: TRUE=dropping whole database */
{
dict_foreign_t* foreign;
dict_table_t* table;
@@ -2099,84 +2188,16 @@ row_drop_table_for_mysql(
que_thr_t* thr;
que_t* graph;
ulint err;
- char* str1;
- char* str2;
- ulint len;
ulint namelen;
- ulint keywordlen;
ibool success;
ibool locked_dictionary = FALSE;
- char buf[OS_FILE_MAX_PATH + 2000];
-
- ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
- ut_a(name != NULL);
-
- if (srv_created_new_raw) {
- fprintf(stderr,
- "InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
- "InnoDB: database modifications by the user. Shut down\n"
- "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n");
-
- return(DB_ERROR);
- }
-
- trx->op_info = (char *) "dropping table";
-
- trx_start_if_not_started(trx);
-
- namelen = ut_strlen(name);
- keywordlen = ut_strlen((char *) "innodb_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(name + namelen - keywordlen,
- (char *) "innodb_monitor", keywordlen)) {
-
- /* Table name ends to characters innodb_monitor:
- stop monitor prints */
-
- srv_print_innodb_monitor = FALSE;
- srv_print_innodb_lock_monitor = FALSE;
- }
-
- keywordlen = ut_strlen((char *) "innodb_lock_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(name + namelen - keywordlen,
- (char *) "innodb_lock_monitor",
- keywordlen)) {
-
- srv_print_innodb_monitor = FALSE;
- srv_print_innodb_lock_monitor = FALSE;
- }
-
- keywordlen = ut_strlen((char *) "innodb_tablespace_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(name + namelen - keywordlen,
- (char *) "innodb_tablespace_monitor",
- keywordlen)) {
-
- srv_print_innodb_tablespace_monitor = FALSE;
- }
-
- keywordlen = ut_strlen((char *) "innodb_table_monitor");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(name + namelen - keywordlen,
- (char *) "innodb_table_monitor",
- keywordlen)) {
-
- srv_print_innodb_table_monitor = FALSE;
- }
-
+ char* quoted_name;
+ char* sql;
/* We use the private SQL parser of Innobase to generate the
query graphs needed in deleting the dictionary data from system
tables in Innobase. Deleting a row from SYS_INDEXES table also
frees the file segments of the B-tree associated with the index. */
-
- str1 = (char *)
+ static const char str1[] =
"PROCEDURE DROP_TABLE_PROC () IS\n"
"table_name CHAR;\n"
"sys_foreign_id CHAR;\n"
@@ -2185,10 +2206,9 @@ row_drop_table_for_mysql(
"foreign_id CHAR;\n"
"found INT;\n"
"BEGIN\n"
- "table_name := '";
-
- str2 = (char *)
- "';\n"
+ "table_name := ";
+ static const char str2[] =
+ ";\n"
"SELECT ID INTO table_id\n"
"FROM SYS_TABLES\n"
"WHERE NAME = table_name;\n"
@@ -2238,16 +2258,74 @@ row_drop_table_for_mysql(
"COMMIT WORK;\n"
"END;\n";
- len = ut_strlen(str1);
+ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+ ut_a(name != NULL);
+
+ if (srv_created_new_raw) {
+ fputs(
+ "InnoDB: A new raw disk partition was initialized or\n"
+ "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ "InnoDB: database modifications by the user. Shut down\n"
+ "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
+
+ return(DB_ERROR);
+ }
- ut_memcpy(buf, str1, len);
- ut_memcpy(buf + len, name, ut_strlen(name));
+ trx->op_info = (char *) "dropping table";
- len += ut_strlen(name);
+ trx_start_if_not_started(trx);
- ut_memcpy(buf + len, str2, ut_strlen(str2) + 1);
+ namelen = strlen(name) + 1;
- ut_a(strlen(buf) < OS_FILE_MAX_PATH + 2000);
+ if (namelen == sizeof S_innodb_monitor
+ && !memcmp(name, S_innodb_monitor,
+ sizeof S_innodb_monitor)) {
+
+ /* Table name equals "innodb_monitor":
+ stop monitor prints */
+
+ srv_print_innodb_monitor = FALSE;
+ srv_print_innodb_lock_monitor = FALSE;
+ } else if (namelen == sizeof S_innodb_lock_monitor
+ && !memcmp(name, S_innodb_lock_monitor,
+ sizeof S_innodb_lock_monitor)) {
+ srv_print_innodb_monitor = FALSE;
+ srv_print_innodb_lock_monitor = FALSE;
+ } else if (namelen == sizeof S_innodb_tablespace_monitor
+ && !memcmp(name, S_innodb_tablespace_monitor,
+ sizeof S_innodb_tablespace_monitor)) {
+
+ srv_print_innodb_tablespace_monitor = FALSE;
+ } else if (namelen == sizeof S_innodb_table_monitor
+ && !memcmp(name, S_innodb_table_monitor,
+ sizeof S_innodb_table_monitor)) {
+
+ srv_print_innodb_table_monitor = FALSE;
+ }
+
+ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+ ut_a(name != NULL);
+
+ if (srv_created_new_raw) {
+ fputs(
+ "InnoDB: A new raw disk partition was initialized or\n"
+ "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ "InnoDB: database modifications by the user. Shut down\n"
+ "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
+
+ return(DB_ERROR);
+ }
+
+ quoted_name = mem_strdupq(name, '\'');
+ namelen = strlen(quoted_name);
+ sql = mem_alloc((sizeof str1) + (sizeof str2) - 2 + 1 + namelen);
+ memcpy(sql, str1, (sizeof str1) - 1);
+ memcpy(sql + (sizeof str1) - 1, quoted_name, namelen);
+ memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
@@ -2266,9 +2344,10 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- graph = pars_sql(buf);
+ graph = pars_sql(sql);
ut_a(graph);
+ mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
@@ -2281,15 +2360,14 @@ row_drop_table_for_mysql(
err = DB_TABLE_NOT_FOUND;
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: table %s\n"
- "InnoDB: does not exist in the InnoDB internal\n"
+ fputs(" InnoDB: Error: table ", stderr);
+ ut_print_name(stderr, name);
+ fputs(" does not exist in the InnoDB internal\n"
"InnoDB: data dictionary though MySQL is trying to drop it.\n"
"InnoDB: Have you copied the .frm file of the table to the\n"
"InnoDB: MySQL database directory from another database?\n"
"InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html\n",
- name);
+ "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
goto funct_exit;
}
@@ -2302,8 +2380,10 @@ row_drop_table_for_mysql(
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
- if (foreign && trx->check_foreigns) {
- char* buf = dict_foreign_err_buf;
+ if (foreign && trx->check_foreigns &&
+ !(drop_db && dict_tables_have_same_db(
+ name, foreign->foreign_table_name))) {
+ FILE* ef = dict_foreign_err_file;
/* We only allow dropping a referenced table if
FOREIGN_KEY_CHECKS is set to 0 */
@@ -2311,28 +2391,30 @@ row_drop_table_for_mysql(
err = DB_CANNOT_DROP_CONSTRAINT;
mutex_enter(&dict_foreign_err_mutex);
- ut_sprintf_timestamp(buf);
-
- sprintf(buf + strlen(buf),
- " Cannot drop table %.500s\n", name);
- sprintf(buf + strlen(buf),
-"because it is referenced by %.500s\n", foreign->foreign_table_name);
-
- ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
-
+ rewind(ef);
+ ut_print_timestamp(ef);
+
+ fputs(" Cannot drop table ", ef);
+ ut_print_name(ef, name);
+ fputs("\n"
+ "because it is referenced by ", ef);
+ ut_print_name(ef, foreign->foreign_table_name);
+ putc('\n', ef);
mutex_exit(&dict_foreign_err_mutex);
goto funct_exit;
}
if (table->n_mysql_handles_opened > 0) {
-
+
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Warning: MySQL is trying to drop table %s\n"
+ fputs(" InnoDB: Warning: MySQL is trying to drop table ",
+ stderr);
+ ut_print_name(stderr, table->name);
+ fputs("\n"
"InnoDB: though there are still open handles to it.\n"
"InnoDB: Adding the table to the background drop queue.\n",
- table->name);
+ stderr);
row_add_table_to_background_drop_list(table);
@@ -2342,13 +2424,14 @@ row_drop_table_for_mysql(
}
if (table->n_foreign_key_checks_running > 0) {
-
+
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: You are trying to drop table %s\n"
+ fputs(" InnoDB: You are trying to drop table ", stderr);
+ ut_print_name(stderr, table->name);
+ fputs("\n"
"InnoDB: though there are foreign key check running on it.\n"
"InnoDB: Adding the table to the background drop queue.\n",
- table->name);
+ stderr);
row_add_table_to_background_drop_list(table);
@@ -2384,9 +2467,10 @@ row_drop_table_for_mysql(
if (dict_load_table(name) != NULL) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: not able to remove table %s from the dictionary cache!\n",
- name);
+ fputs(" InnoDB: Error: not able to remove table ",
+ stderr);
+ ut_print_name(stderr, name);
+ fputs(" from the dictionary cache!\n", stderr);
err = DB_ERROR;
}
@@ -2454,7 +2538,7 @@ loop:
row_mysql_lock_data_dictionary(trx);
while ((table_name = dict_get_first_table_name_in_db(name))) {
- ut_a(memcmp(table_name, name, strlen(name)) == 0);
+ ut_a(strcmp(table_name, name) == 0);
table = dict_table_get_low(table_name);
@@ -2467,10 +2551,13 @@ loop:
row_mysql_unlock_data_dictionary(trx);
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Warning: MySQL is trying to drop database %s\n"
- "InnoDB: though there are still open handles to table %s.\n",
- name, table_name);
+ fputs(
+ " InnoDB: Warning: MySQL is trying to drop database ", stderr);
+ ut_print_name(stderr, name);
+ fputs("\n"
+ "InnoDB: though there are still open handles to table ", stderr);
+ ut_print_name(stderr, table_name);
+ fputs(".\n", stderr);
os_thread_sleep(1000000);
@@ -2479,14 +2566,17 @@ loop:
goto loop;
}
- err = row_drop_table_for_mysql(table_name, trx);
+ err = row_drop_table_for_mysql(table_name, trx, TRUE);
mem_free(table_name);
if (err != DB_SUCCESS) {
- fprintf(stderr,
- "InnoDB: DROP DATABASE %s failed with error %lu for table %s\n",
- name, (ulong) err, table_name);
+ fputs("InnoDB: DROP DATABASE ", stderr);
+ ut_print_name(stderr, name);
+ fprintf(stderr, " failed with error %lu for table ",
+ (ulint) err);
+ ut_print_name(stderr, table_name);
+ putc('\n', stderr);
break;
}
}
@@ -2507,19 +2597,11 @@ static
ibool
row_is_mysql_tmp_table_name(
/*========================*/
- /* out: TRUE if temporary table */
- char* name) /* in: table name in the form 'database/tablename' */
+ /* out: TRUE if temporary table */
+ const char* name) /* in: table name in the form
+ 'database/tablename' */
{
- ulint i;
-
- for (i = 0; i + 5 <= ut_strlen(name); i++) {
- if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) {
-
- return(TRUE);
- }
- }
-
- return(FALSE);
+ return(strstr(name, "/#sql") != NULL);
}
/*************************************************************************
@@ -2537,40 +2619,113 @@ row_rename_table_for_mysql(
que_thr_t* thr;
que_t* graph = NULL;
ulint err;
- char* str1;
- char* str2;
- char* str3;
+ /* We use the private SQL parser of Innobase to generate the
+ query graphs needed in deleting the dictionary data from system
+ tables in Innobase. Deleting a row from SYS_INDEXES table also
+ frees the file segments of the B-tree associated with the index. */
+ static const char str1[] =
+ "PROCEDURE RENAME_TABLE_PROC () IS\n"
+ "new_table_name CHAR;\n"
+ "old_table_name CHAR;\n"
+ "gen_constr_prefix CHAR;\n"
+ "new_db_name CHAR;\n"
+ "foreign_id CHAR;\n"
+ "new_foreign_id CHAR;\n"
+ "old_db_name_len INT;\n"
+ "old_t_name_len INT;\n"
+ "new_db_name_len INT;\n"
+ "id_len INT;\n"
+ "found INT;\n"
+ "BEGIN\n"
+ "new_table_name := '";
+ static const char str2[] =
+ "';\nold_table_name := '";
+ static const char str3[] =
+ "';\n"
+ "UPDATE SYS_TABLES SET NAME = new_table_name\n"
+ "WHERE NAME = old_table_name;\n";
+ static const char str4a1[] = /* drop some constraints of tmp tables */
+ "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '";
+ static const char str4a2[] = "';\n"
+ "DELETE FROM SYS_FOREIGN WHERE ID = '";
+ static const char str4a3[] = "';\n";
+ static const char str4b[] = /* rename all constraints */
+ "found := 1;\n"
+ "old_db_name_len := INSTR(old_table_name, '/') - 1;\n"
+ "new_db_name_len := INSTR(new_table_name, '/') - 1;\n"
+ "new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n"
+ "old_t_name_len := LENGTH(old_table_name);\n"
+ "gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n"
+ "WHILE found = 1 LOOP\n"
+ " SELECT ID INTO foreign_id\n"
+ " FROM SYS_FOREIGN\n"
+ " WHERE FOR_NAME = old_table_name;\n"
+ " IF (SQL % NOTFOUND) THEN\n"
+ " found := 0;\n"
+ " ELSE\n"
+ " UPDATE SYS_FOREIGN\n"
+ " SET FOR_NAME = new_table_name\n"
+ " WHERE ID = foreign_id;\n"
+ " id_len := LENGTH(foreign_id);\n"
+ " IF (INSTR(foreign_id, '/') > 0) THEN\n"
+ " IF (INSTR(foreign_id,\n"
+ " gen_constr_prefix) > 0)\n"
+ " THEN\n"
+ " new_foreign_id :=\n"
+ " CONCAT(new_table_name,\n"
+ " SUBSTR(foreign_id, old_t_name_len,\n"
+ " id_len - old_t_name_len));\n"
+ " ELSE\n"
+ " new_foreign_id :=\n"
+ " CONCAT(new_db_name,\n"
+ " SUBSTR(foreign_id,\n"
+ " old_db_name_len,\n"
+ " id_len - old_db_name_len));\n"
+ " END IF;\n"
+ " UPDATE SYS_FOREIGN\n"
+ " SET ID = new_foreign_id\n"
+ " WHERE ID = foreign_id;\n"
+ " UPDATE SYS_FOREIGN_COLS\n"
+ " SET ID = new_foreign_id\n"
+ " WHERE ID = foreign_id;\n"
+ " END IF;\n"
+ " END IF;\n"
+ "END LOOP;\n"
+ "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
+ "WHERE REF_NAME = old_table_name;\n";
+ static const char str5[] =
+ "END;\n";
+
mem_heap_t* heap = NULL;
- char** constraints_to_drop = NULL;
+ const char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0;
- ibool recovering_temp_table = FALSE;
- ulint namelen;
- ulint keywordlen;
+ ibool recovering_temp_table = FALSE;
ulint len;
ulint i;
- char* db_name;
- ibool success;
- char buf[2 * OS_FILE_MAX_PATH];
+ ibool success;
+ /* length of database name; 0 if not renaming to a temporary table */
+ ulint db_name_len;
+ char* sql;
+ char* sqlend;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
ut_a(new_name != NULL);
if (srv_created_new_raw || srv_force_recovery) {
- fprintf(stderr,
+ fputs(
"InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n");
+ "InnoDB: with raw, and innodb_force_... is removed.\n",
+ stderr);
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
- if (0 == ut_strcmp(new_name, (char*)"mysql/host")
- || 0 == ut_strcmp(new_name, (char*)"mysql/user")
- || 0 == ut_strcmp(new_name, (char*)"mysql/db")) {
+ if (row_mysql_is_system_table(new_name)) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
@@ -2584,21 +2739,13 @@ row_rename_table_for_mysql(
trx->op_info = (char *) "renaming table";
trx_start_if_not_started(trx);
- namelen = ut_strlen(new_name);
-
- keywordlen = ut_strlen("_recover_innodb_tmp_table");
-
- if (namelen >= keywordlen
- && 0 == ut_memcmp(new_name + namelen - keywordlen,
- (char*)"_recover_innodb_tmp_table", keywordlen)) {
-
- recovering_temp_table = TRUE;
- }
+ if (row_mysql_is_recovered_tmp_table(new_name)) {
- /* Serialize data dictionary operations with dictionary mutex:
- no deadlocks can occur then in these operations */
+ recovering_temp_table = TRUE;
+ } else {
+ /* Serialize data dictionary operations with dictionary mutex:
+ no deadlocks can occur then in these operations */
- if (!recovering_temp_table) {
row_mysql_lock_data_dictionary(trx);
}
@@ -2633,26 +2780,12 @@ row_rename_table_for_mysql(
goto funct_exit;
}
- str1 = (char *)
- "PROCEDURE RENAME_TABLE_PROC () IS\n"
- "new_table_name CHAR;\n"
- "old_table_name CHAR;\n"
- "gen_constr_prefix CHAR;\n"
- "new_db_name CHAR;\n"
- "foreign_id CHAR;\n"
- "new_foreign_id CHAR;\n"
- "old_db_name_len INT;\n"
- "old_t_name_len INT;\n"
- "new_db_name_len INT;\n"
- "id_len INT;\n"
- "found INT;\n"
- "BEGIN\n"
- "new_table_name :='";
-
- str2 = (char *)
- "';\nold_table_name := '";
+ /* calculate the length of the SQL string */
+ len = (sizeof str1) + (sizeof str2) + (sizeof str3) + (sizeof str5) - 4
+ + ut_strlenq(new_name, '\'') + ut_strlenq(old_name, '\'');
if (row_is_mysql_tmp_table_name(new_name)) {
+ db_name_len = dict_get_db_name_len(old_name) + 1;
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
@@ -2671,123 +2804,90 @@ row_rename_table_for_mysql(
goto funct_exit;
}
- str3 = mem_heap_alloc(heap,
- 1000 + 1000 * n_constraints_to_drop);
- *str3 = '\0';
- sprintf(str3,
- "';\n"
- "UPDATE SYS_TABLES SET NAME = new_table_name\n"
- "WHERE NAME = old_table_name;\n");
-
- db_name = mem_heap_alloc(heap, 1 + dict_get_db_name_len(
- old_name));
- ut_memcpy(db_name, old_name, dict_get_db_name_len(old_name));
- db_name[dict_get_db_name_len(old_name)] = '\0';
+ /* reserve space for all database names */
+ len += 2 * n_constraints_to_drop
+ * (ut_strlenq(old_name, '\'')
+ - ut_strlenq(old_name + db_name_len, '\''));
+
+ for (i = 0; i < n_constraints_to_drop; i++) {
+ ulint addlen
+ = 2 * ut_strlenq(constraints_to_drop[i], '\'')
+ + ((sizeof str4a1) + (sizeof str4a2)
+ + (sizeof str4a3) - 3);
+ if (!strchr(constraints_to_drop[i], '/')) {
+ addlen *= 2;
+ }
+ len += addlen;
+ }
+ } else {
+ db_name_len = 0;
+ len += (sizeof str4b) - 1;
+ }
+ sql = sqlend = mem_alloc(len + 1);
+ memcpy(sql, str1, (sizeof str1) - 1);
+ sqlend += (sizeof str1) - 1;
+ sqlend = ut_strcpyq(sqlend, '\'', new_name);
+ memcpy(sqlend, str2, (sizeof str2) - 1);
+ sqlend += (sizeof str2) - 1;
+ sqlend = ut_strcpyq(sqlend, '\'', old_name);
+ memcpy(sqlend, str3, (sizeof str3) - 1);
+ sqlend += (sizeof str3) - 1;
+
+ if (db_name_len) {
/* Internally, old format < 4.0.18 constraints have as the
constraint id <number>_<number>, while new format constraints
have <databasename>/<constraintname>. */
for (i = 0; i < n_constraints_to_drop; i++) {
+ memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
+ sqlend += (sizeof str4a1) - 1;
+ sqlend = ut_memcpyq(sqlend, '\'',
+ old_name, db_name_len);
+ sqlend = ut_strcpyq(sqlend, '\'',
+ constraints_to_drop[i]);
+ memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
+ sqlend += (sizeof str4a2) - 1;
+ sqlend = ut_memcpyq(sqlend, '\'',
+ old_name, db_name_len);
+ sqlend = ut_strcpyq(sqlend, '\'',
+ constraints_to_drop[i]);
+ memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
+ sqlend += (sizeof str4a3) - 1;
- sprintf(str3 + strlen(str3),
- "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s/%s';\n"
- "DELETE FROM SYS_FOREIGN WHERE ID = '%s/%s';\n",
- db_name, constraints_to_drop[i],
- db_name, constraints_to_drop[i]);
-
- if (!ut_str_contains(constraints_to_drop[i], '/')) {
+ if (!strchr(constraints_to_drop[i], '/')) {
/* If this happens to be an old format
constraint, let us delete it. Since all new
format constraints contain '/', it does no
harm to run these DELETEs anyway. */
- sprintf(str3 + strlen(str3),
- "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n"
- "DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n",
- constraints_to_drop[i],
- constraints_to_drop[i]);
+ memcpy(sqlend, str4a1, (sizeof str4a1) - 1);
+ sqlend += (sizeof str4a1) - 1;
+ sqlend = ut_strcpyq(sqlend, '\'',
+ constraints_to_drop[i]);
+ memcpy(sqlend, str4a2, (sizeof str4a2) - 1);
+ sqlend += (sizeof str4a2) - 1;
+ sqlend = ut_strcpyq(sqlend, '\'',
+ constraints_to_drop[i]);
+ memcpy(sqlend, str4a3, (sizeof str4a3) - 1);
+ sqlend += (sizeof str4a3) - 1;
}
}
+ }
+ else {
+ memcpy(sqlend, str4b, (sizeof str4b) - 1);
+ sqlend += (sizeof str4b) - 1;
+ }
- sprintf(str3 + strlen(str3),
- "END;\n");
+ memcpy(sqlend, str5, sizeof str5);
+ sqlend += sizeof str5;
- ut_a(strlen(str3) < 1000 + 1000 * n_constraints_to_drop);
- } else {
- str3 = (char*)
- "';\n"
- "UPDATE SYS_TABLES SET NAME = new_table_name\n"
- "WHERE NAME = old_table_name;\n"
- "found := 1;\n"
- "old_db_name_len := INSTR(old_table_name, '/') - 1;\n"
- "new_db_name_len := INSTR(new_table_name, '/') - 1;\n"
- "new_db_name := SUBSTR(new_table_name, 0, new_db_name_len);\n"
- "old_t_name_len := LENGTH(old_table_name);\n"
- "gen_constr_prefix := CONCAT(old_table_name, '_ibfk_');\n"
- "WHILE found = 1 LOOP\n"
- " SELECT ID INTO foreign_id\n"
- " FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = old_table_name;\n"
- " IF (SQL % NOTFOUND) THEN\n"
- " found := 0;\n"
- " ELSE\n"
- " UPDATE SYS_FOREIGN\n"
- " SET FOR_NAME = new_table_name\n"
- " WHERE ID = foreign_id;\n"
- " id_len := LENGTH(foreign_id);\n"
- " IF (INSTR(foreign_id, '/') > 0) THEN\n"
- " IF (INSTR(foreign_id,\n"
- " gen_constr_prefix) > 0)\n"
- " THEN\n"
- " new_foreign_id :=\n"
- " CONCAT(new_table_name,\n"
- " SUBSTR(foreign_id, old_t_name_len,\n"
- " id_len - old_t_name_len));\n"
- " ELSE\n"
- " new_foreign_id :=\n"
- " CONCAT(new_db_name,\n"
- " SUBSTR(foreign_id,\n"
- " old_db_name_len,\n"
- " id_len - old_db_name_len));\n"
- " END IF;\n"
- " UPDATE SYS_FOREIGN\n"
- " SET ID = new_foreign_id\n"
- " WHERE ID = foreign_id;\n"
- " UPDATE SYS_FOREIGN_COLS\n"
- " SET ID = new_foreign_id\n"
- " WHERE ID = foreign_id;\n"
- " END IF;\n"
- " END IF;\n"
- "END LOOP;\n"
- "UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
- "WHERE REF_NAME = old_table_name;\n"
- "END;\n";
- }
-
- len = ut_strlen(str1);
-
- ut_memcpy(buf, str1, len);
-
- ut_memcpy(buf + len, new_name, ut_strlen(new_name));
-
- len += ut_strlen(new_name);
-
- ut_memcpy(buf + len, str2, ut_strlen(str2));
-
- len += ut_strlen(str2);
-
- ut_memcpy(buf + len, old_name, ut_strlen(old_name));
-
- len += ut_strlen(old_name);
-
- ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
+ ut_a(sqlend == sql + len + 1);
- ut_a(strlen(buf) < 2 * OS_FILE_MAX_PATH);
-
- graph = pars_sql(buf);
+ graph = pars_sql(sql);
ut_a(graph);
+ mem_free(sql);
graph->trx = trx;
trx->graph = NULL;
@@ -2915,7 +3015,6 @@ row_scan_and_check_index(
int cmp;
ibool contains_null;
ulint i;
- char err_buf[1000];
*n_rows = 0;
@@ -2952,7 +3051,7 @@ loop:
template */
rec = buf + mach_read_from_4(buf);
-
+
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
@@ -2976,32 +3075,25 @@ loop:
}
if (cmp > 0) {
- fprintf(stderr,
- "Error: index records in a wrong order in index %s\n",
- index->name);
-
- dtuple_sprintf(err_buf, 900, prev_entry);
- fprintf(stderr, "InnoDB: prev record %s\n", err_buf);
-
- rec_sprintf(err_buf, 900, rec);
- fprintf(stderr, "InnoDB: record %s\n", err_buf);
-
+ fputs("InnoDB: index records in a wrong order in ",
+ stderr);
+ not_ok:
+ dict_index_name_print(stderr, index);
+ fputs("\n"
+ "InnoDB: prev record ", stderr);
+ dtuple_print(stderr, prev_entry);
+ fputs("\n"
+ "InnoDB: record ", stderr);
+ rec_print(stderr, rec);
+ putc('\n', stderr);
is_ok = FALSE;
} else if ((index->type & DICT_UNIQUE)
&& !contains_null
&& matched_fields >=
dict_index_get_n_ordering_defined_by_user(index)) {
- fprintf(stderr, "Error: duplicate key in index %s\n",
- index->name);
-
- dtuple_sprintf(err_buf, 900, prev_entry);
- fprintf(stderr, "InnoDB: prev record %s\n", err_buf);
-
- rec_sprintf(err_buf, 900, rec);
- fprintf(stderr, "InnoDB: record %s\n", err_buf);
-
- is_ok = FALSE;
+ fputs("InnoDB: duplicate key in ", stderr);
+ goto not_ok;
}
}
@@ -3045,7 +3137,9 @@ row_check_table_for_mysql(
index = dict_table_get_first_index(table);
while (index != NULL) {
- /* fprintf(stderr, "Validating index %s\n", index->name); */
+ /* fputs("Validating index ", stderr);
+ ut_print_name(stderr, index->name);
+ putc('\n', stderr); */
if (!btr_validate_tree(index->tree)) {
ret = DB_ERROR;