diff options
Diffstat (limited to 'innobase/row/row0mysql.c')
-rw-r--r-- | innobase/row/row0mysql.c | 165 |
1 files changed, 140 insertions, 25 deletions
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index cf7a3efcdfc..49e5aeac2e4 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -287,7 +287,7 @@ handle_new_error: } else { fprintf(stderr, "InnoDB: unknown error code %lu\n", (ulong) err); - ut_a(0); + ut_error; } if (trx->error_state != DB_SUCCESS) { @@ -402,7 +402,7 @@ row_prebuilt_free( mem_analyze_corruption((byte*)prebuilt); - ut_a(0); + ut_error; } prebuilt->magic_n = ROW_PREBUILT_FREED; @@ -450,7 +450,7 @@ row_prebuilt_free( mem_analyze_corruption( prebuilt->fetch_cache[i]); - ut_a(0); + ut_error; } mem_free((prebuilt->fetch_cache[i]) - 4); @@ -482,7 +482,7 @@ row_update_prebuilt_trx( mem_analyze_corruption((byte*)trx); - ut_a(0); + ut_error; } if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { @@ -493,7 +493,7 @@ row_update_prebuilt_trx( mem_analyze_corruption((byte*)prebuilt); - ut_a(0); + ut_error; } prebuilt->trx = trx; @@ -720,7 +720,7 @@ row_insert_for_mysql( mem_analyze_corruption((byte*)prebuilt); - ut_a(0); + ut_error; } if (srv_created_new_raw || srv_force_recovery) { @@ -936,7 +936,7 @@ row_update_for_mysql( mem_analyze_corruption((byte*)prebuilt); - ut_a(0); + ut_error; } if (srv_created_new_raw || srv_force_recovery) { @@ -1289,9 +1289,11 @@ row_create_table_for_mysql( ulint err; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); +#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); - ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); ut_ad(mutex_own(&(dict_sys->mutex))); +#endif /* UNIV_SYNC_DEBUG */ + ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); if (srv_created_new_raw) { fprintf(stderr, @@ -1408,10 +1410,12 @@ row_create_table_for_mysql( "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"); - +#ifdef UNIV_MEM_DEBUG ut_a(mem_validate()); - printf("Memory validated\n"); +#else /* UNIV_MEM_DEBUG */ + puts("Memory NOT validated (recompile with UNIV_MEM_DEBUG)"); +#endif /* UNIV_MEM_DEBUG */ } heap = mem_heap_create(512); @@ -1422,8 +1426,7 @@ row_create_table_for_mysql( thr = pars_complete_graph_for_exec(node, trx, heap); - ut_a(thr == que_fork_start_command(que_node_get_parent(thr), - SESS_COMM_EXECUTE, 0)); + ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); que_run_threads(thr); err = trx->error_state; @@ -1494,8 +1497,10 @@ row_create_index_for_mysql( ulint err; ulint i, j; +#ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); ut_ad(mutex_own(&(dict_sys->mutex))); +#endif /* UNIV_SYNC_DEBUG */ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); trx->op_info = (char *) "creating index"; @@ -1550,8 +1555,7 @@ row_create_index_for_mysql( thr = pars_complete_graph_for_exec(node, trx, heap); - ut_a(thr == que_fork_start_command(que_node_get_parent(thr), - SESS_COMM_EXECUTE, 0)); + ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); que_run_threads(thr); err = trx->error_state; @@ -1602,8 +1606,10 @@ row_table_add_foreign_constraints( ulint keywordlen; ulint err; +#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ ut_a(sql_string); trx->op_info = (char *) "adding foreign keys"; @@ -1774,7 +1780,9 @@ row_get_background_drop_list_len_low(void) /*======================================*/ /* out: how many tables in list */ { +#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); +#endif /* UNIV_SYNC_DEBUG */ if (!row_mysql_drop_list_inited) { @@ -1926,7 +1934,7 @@ row_discard_tablespace_for_mysql( graph->fork_type = QUE_FORK_MYSQL_INTERFACE; - ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0)); + ut_a(thr = que_fork_start_command(graph)); que_run_threads(thr); @@ -2085,6 +2093,7 @@ row_drop_table_for_mysql( char* name, /* in: table name */ trx_t* trx) /* in: transaction handle */ { + dict_foreign_t* foreign; dict_table_t* table; ulint space_id; que_thr_t* thr; @@ -2252,8 +2261,10 @@ row_drop_table_for_mysql( locked_dictionary = TRUE; } +#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ graph = pars_sql(buf); @@ -2282,6 +2293,38 @@ row_drop_table_for_mysql( goto funct_exit; } + /* Check if the table is referenced by foreign key constraints from + some other table (not the table itself) */ + + foreign = UT_LIST_GET_FIRST(table->referenced_list); + + while (foreign && foreign->foreign_table == table) { + foreign = UT_LIST_GET_NEXT(referenced_list, foreign); + } + + if (foreign && trx->check_foreigns) { + char* buf = dict_foreign_err_buf; + + /* We only allow dropping a referenced table if + FOREIGN_KEY_CHECKS is set to 0 */ + + 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); + + mutex_exit(&dict_foreign_err_mutex); + + goto funct_exit; + } + if (table->n_mysql_handles_opened > 0) { ut_print_timestamp(stderr); @@ -2321,7 +2364,7 @@ row_drop_table_for_mysql( trx->dict_operation = TRUE; trx->table_id = table->id; - ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0)); + ut_a(thr = que_fork_start_command(graph)); que_run_threads(thr); @@ -2334,7 +2377,7 @@ row_drop_table_for_mysql( row_mysql_handle_errors(&err, trx, thr, NULL); - ut_a(0); + ut_error; } else { space_id = table->space; dict_table_remove_from_cache(table); @@ -2469,7 +2512,7 @@ row_is_mysql_tmp_table_name( { ulint i; - for (i = 0; i <= ut_strlen(name) - 5; i++) { + for (i = 0; i + 5 <= ut_strlen(name); i++) { if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) { return(TRUE); @@ -2505,6 +2548,7 @@ row_rename_table_for_mysql( ulint keywordlen; ulint len; ulint i; + char* db_name; ibool success; char buf[2 * OS_FILE_MAX_PATH]; @@ -2593,6 +2637,15 @@ row_rename_table_for_mysql( "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 :='"; @@ -2619,32 +2672,94 @@ row_rename_table_for_mysql( } str3 = mem_heap_alloc(heap, - 1000 + 500 * n_constraints_to_drop); + 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'; + + /* 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++) { + sprintf(str3 + strlen(str3), - "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n" - "DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n", + "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 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]); + } } sprintf(str3 + strlen(str3), "END;\n"); - ut_a(strlen(str3) < 1000 + 500 * n_constraints_to_drop); + 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" - "UPDATE SYS_FOREIGN SET FOR_NAME = new_table_name\n" - "WHERE FOR_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"; @@ -2679,7 +2794,7 @@ row_rename_table_for_mysql( graph->fork_type = QUE_FORK_MYSQL_INTERFACE; - ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0)); + ut_a(thr = que_fork_start_command(graph)); que_run_threads(thr); |