Loading innobase/btr/btr0btr.c +13 −0 Original line number Diff line number Diff line Loading @@ -570,6 +570,19 @@ btr_page_get_father_for_rec( node_ptr = btr_cur_get_rec(&cursor); if (btr_node_ptr_get_child_page_no(node_ptr) != buf_frame_get_page_no(page)) { fprintf(stderr, "InnoDB: Corruption of an index tree: table %s, index %s,\n" "InnoDB: father ptr page no %lu, child page no %lu\n", (UT_LIST_GET_FIRST(tree->tree_indexes))->table_name, (UT_LIST_GET_FIRST(tree->tree_indexes))->name, btr_node_ptr_get_child_page_no(node_ptr), buf_frame_get_page_no(page)); page_rec_print(page_rec_get_next(page_get_infimum_rec(page))); page_rec_print(node_ptr); } ut_a(btr_node_ptr_get_child_page_no(node_ptr) == buf_frame_get_page_no(page)); mem_heap_free(heap); Loading innobase/btr/btr0sea.c +1 −1 Original line number Diff line number Diff line Loading @@ -743,7 +743,7 @@ btr_search_guess_on_hash( #ifdef notdefined /* These lines of code can be used in a debug version to check correctness of the searched cursor position: */ the correctness of the searched cursor position: */ info->last_hash_succ = FALSE; Loading innobase/buf/buf0buf.c +64 −18 Original line number Diff line number Diff line Loading @@ -220,6 +220,10 @@ buf_calc_page_checksum( { ulint checksum; /* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO are written outside the buffer pool to the first pages of data files, we have to skip them in page checksum calculation */ checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); + ut_fold_binary(page + FIL_PAGE_DATA, UNIV_PAGE_SIZE - FIL_PAGE_DATA Loading Loading @@ -279,6 +283,7 @@ buf_page_print( ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n%s", UNIV_PAGE_SIZE, buf); Loading @@ -288,6 +293,7 @@ buf_page_print( checksum = buf_calc_page_checksum(read_buf); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Page checksum %lu stored checksum %lu\n", checksum, mach_read_from_4(read_buf + UNIV_PAGE_SIZE Loading Loading @@ -1358,21 +1364,51 @@ buf_page_io_complete( /*=================*/ buf_block_t* block) /* in: pointer to the block in question */ { dulint id; dict_index_t* index; dulint id; ulint io_type; ulint read_page_no; ut_ad(block); io_type = block->io_fix; if (io_type == BUF_IO_READ) { /* If this page is not uninitialized and not in the doublewrite buffer, then the page number should be the same as in block */ read_page_no = mach_read_from_4((block->frame) + FIL_PAGE_OFFSET); if (read_page_no != 0 && !trx_doublewrite_page_inside(read_page_no) && read_page_no != block->offset) { fprintf(stderr, "InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n", read_page_no, block->offset); } #ifdef notdefined if (block->offset != 0 && read_page_no == 0) { /* Check that the page is really uninited */ for (i = 0; i < UNIV_PAGE_SIZE; i++) { if (*((block->frame) + i) != '\0') { fprintf(stderr, "InnoDB: Error: page n:o in the page read in is 0, but page %lu is inited!\n", block->offset); break; } } } #endif /* From version 3.23.38 up we store the page checksum to the 4 upper bytes of the page end lsn field */ to the 4 first bytes of the page end lsn field */ if (buf_page_is_corrupted(block->frame)) { fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: Database page corruption on disk or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, Loading @@ -1381,7 +1417,7 @@ buf_page_io_complete( buf_page_print(block->frame); fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: Database page corruption on disk or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, "InnoDB: You may have to recover from a backup.\n"); Loading @@ -1389,16 +1425,26 @@ buf_page_io_complete( "InnoDB: It is also possible that your operating\n" "InnoDB: system has corrupted its own file cache\n" "InnoDB: and rebooting your computer removes the\n" "InnoDB: error.\n"); "InnoDB: error.\n" "InnoDB: If the corrupt page is an index page\n" "InnoDB: you can also try to fix the corruption\n" "InnoDB: by dumping, dropping, and reimporting\n" "InnoDB: the corrupt table. You can use CHECK\n" "InnoDB: TABLE to scan your table for corruption.\n" "InnoDB: Look also at section 6.1 of\n" "InnoDB: http://www.innodb.com/ibman.html about\n" "InnoDB: forcing recovery.\n"); if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { fprintf(stderr, "InnoDB: Ending processing because of a corrupt database page.\n"); exit(1); } } if (recv_recovery_is_on()) { recv_recover_page(TRUE, block->frame, block->space, block->offset); recv_recover_page(FALSE, TRUE, block->frame, block->space, block->offset); } if (!recv_no_ibuf_operations) { Loading innobase/buf/buf0flu.c +30 −17 Original line number Diff line number Diff line Loading @@ -327,6 +327,34 @@ buf_flush_post_to_doublewrite_buf( mutex_exit(&(trx_doublewrite->mutex)); } /************************************************************************ Initializes a page for writing to the tablespace. */ void buf_flush_init_for_writing( /*=======================*/ byte* page, /* in: page */ dulint newest_lsn, /* in: newest modification lsn to the page */ ulint space, /* in: space id */ ulint page_no) /* in: page number */ { /* Write the newest modification lsn to the page */ mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn); mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, newest_lsn); /* Write to the page the space id and page number */ mach_write_to_4(page + FIL_PAGE_SPACE, space); mach_write_to_4(page + FIL_PAGE_OFFSET, page_no); /* We overwrite the first 4 bytes of the end lsn field to store a page checksum */ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, buf_calc_page_checksum(page)); } /************************************************************************ Does an asynchronous write of a buffer page. NOTE: in simulated aio and also when the doublewrite buffer is used, we must call Loading @@ -349,23 +377,8 @@ buf_flush_write_block_low( /* Force the log to the disk before writing the modified block */ log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS); #endif /* Write the newest modification lsn to the page */ mach_write_to_8(block->frame + FIL_PAGE_LSN, block->newest_modification); mach_write_to_8(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, block->newest_modification); /* Write to the page the space id and page number */ mach_write_to_4(block->frame + FIL_PAGE_SPACE, block->space); mach_write_to_4(block->frame + FIL_PAGE_OFFSET, block->offset); /* We overwrite the first 4 bytes of the end lsn field to store a page checksum */ mach_write_to_4(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, buf_calc_page_checksum(block->frame)); buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); if (!trx_doublewrite) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, Loading innobase/dict/dict0dict.c +185 −14 Original line number Diff line number Diff line Loading @@ -281,7 +281,8 @@ dict_table_autoinc_initialize( } /************************************************************************ Gets the next autoinc value, 0 if not yet initialized. */ Gets the next autoinc value, 0 if not yet initialized. If initialized, increments the counter by 1. */ ib_longlong dict_table_autoinc_get( Loading @@ -306,6 +307,32 @@ dict_table_autoinc_get( return(value); } /************************************************************************ Reads the autoinc counter value, 0 if not yet initialized. Does not increment the counter. */ ib_longlong dict_table_autoinc_read( /*====================*/ /* out: value of the counter */ dict_table_t* table) /* in: table */ { ib_longlong value; mutex_enter(&(table->autoinc_mutex)); if (!table->autoinc_inited) { value = 0; } else { value = table->autoinc; } mutex_exit(&(table->autoinc_mutex)); return(value); } /************************************************************************ Updates the autoinc counter if the value supplied is bigger than the current value. If not inited, does nothing. */ Loading Loading @@ -644,7 +671,10 @@ dict_table_rename_in_cache( /*=======================*/ /* out: TRUE if success */ dict_table_t* table, /* in: table */ char* new_name) /* in: new name */ char* new_name, /* in: new name */ ibool rename_also_foreigns)/* in: in ALTER TABLE we want to preserve the original table name in constraints which reference it */ { dict_foreign_t* foreign; dict_index_t* index; Loading Loading @@ -702,6 +732,41 @@ dict_table_rename_in_cache( index = dict_table_get_next_index(index); } if (!rename_also_foreigns) { /* In ALTER TABLE we think of the rename table operation in the direction table -> temporary table (#sql...) as dropping the table with the old name and creating a new with the new name. Thus we kind of drop the constraints from the dictionary cache here. The foreign key constraints will be inherited to the new table from the system tables through a call of dict_load_foreigns. */ /* Remove the foreign constraints from the cache */ foreign = UT_LIST_GET_LAST(table->foreign_list); while (foreign != NULL) { dict_foreign_remove_from_cache(foreign); foreign = UT_LIST_GET_LAST(table->foreign_list); } /* Reset table field in referencing constraints */ foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign != NULL) { foreign->referenced_table = NULL; foreign->referenced_index = NULL; foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } /* Make the list of referencing constraints empty */ UT_LIST_INIT(table->referenced_list); return(TRUE); } /* Update the table name fields in foreign constraints */ foreign = UT_LIST_GET_FIRST(table->foreign_list); Loading Loading @@ -768,8 +833,6 @@ dict_table_remove_from_cache( foreign = UT_LIST_GET_LAST(table->foreign_list); while (foreign != NULL) { ut_a(0 == ut_strcmp(foreign->foreign_table_name, table->name)); dict_foreign_remove_from_cache(foreign); foreign = UT_LIST_GET_LAST(table->foreign_list); } Loading @@ -779,8 +842,6 @@ dict_table_remove_from_cache( foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign != NULL) { ut_a(0 == ut_strcmp(foreign->referenced_table_name, table->name)); foreign->referenced_table = NULL; foreign->referenced_index = NULL; Loading Loading @@ -1630,6 +1691,7 @@ dict_foreign_add_to_cache( dict_table_t* ref_table; dict_foreign_t* for_in_cache = NULL; dict_index_t* index; ibool added_to_referenced_list = FALSE; ut_ad(mutex_own(&(dict_sys->mutex))); Loading Loading @@ -1673,6 +1735,7 @@ dict_foreign_add_to_cache( UT_LIST_ADD_LAST(referenced_list, ref_table->referenced_list, for_in_cache); added_to_referenced_list = TRUE; } if (for_in_cache->foreign_table == NULL && for_table) { Loading @@ -1683,6 +1746,12 @@ dict_foreign_add_to_cache( if (index == NULL) { if (for_in_cache == foreign) { if (added_to_referenced_list) { UT_LIST_REMOVE(referenced_list, ref_table->referenced_list, for_in_cache); } mem_heap_free(foreign->heap); } Loading Loading @@ -1802,9 +1871,14 @@ dict_scan_col( return(ptr); } if (*ptr == '`') { ptr++; } old_ptr = ptr; while (!isspace(*ptr) && *ptr != ',' && *ptr != ')') { while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') { ptr++; } Loading @@ -1825,6 +1899,10 @@ dict_scan_col( } } if (*ptr == '`') { ptr++; } return(ptr); } Loading Loading @@ -1855,9 +1933,13 @@ dict_scan_table_name( return(ptr); } if (*ptr == '`') { ptr++; } old_ptr = ptr; while (!isspace(*ptr) && *ptr != '(') { while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') { if (*ptr == '.') { dot_ptr = ptr; } Loading Loading @@ -1898,6 +1980,10 @@ dict_scan_table_name( *table = dict_table_get_low(second_table_name); if (*ptr == '`') { ptr++; } return(ptr); } Loading Loading @@ -1940,8 +2026,8 @@ dict_create_foreign_constraints( /*============================*/ /* out: error code or DB_SUCCESS */ trx_t* trx, /* in: transaction */ char* sql_string, /* in: table create statement where foreign keys are declared like: char* sql_string, /* in: table create or ALTER TABLE statement where foreign keys are declared like: FOREIGN KEY (a, b) REFERENCES table2(c, d), table2 can be written also with the database name before it: test.table2; the default Loading @@ -1967,10 +2053,11 @@ dict_create_foreign_constraints( if (table == NULL) { return(DB_ERROR); } loop: ptr = dict_scan_to(ptr, "FOREIGN"); if (*ptr == '\0' || dict_bracket_count(sql_string, ptr) != 1) { if (*ptr == '\0') { /* The following call adds the foreign key constraints to the data dictionary system tables on disk */ Loading Loading @@ -2883,12 +2970,89 @@ dict_field_print_low( printf(" %s", field->name); } /************************************************************************** Sprintfs to a string info on foreign keys of a table in a format suitable for CREATE TABLE. */ static void dict_print_info_on_foreign_keys_in_create_format( /*=============================================*/ char* buf, /* in: auxiliary buffer of 10000 chars */ char* str, /* in/out: pointer to a string */ ulint len, /* in: space in str available for info */ dict_table_t* table) /* in: table */ { dict_foreign_t* foreign; ulint i; char* buf2; buf2 = buf; mutex_enter(&(dict_sys->mutex)); foreign = UT_LIST_GET_FIRST(table->foreign_list); if (foreign == NULL) { mutex_exit(&(dict_sys->mutex)); return; } while (foreign != NULL) { buf2 += sprintf(buf2, ",\n FOREIGN KEY ("); for (i = 0; i < foreign->n_fields; i++) { buf2 += sprintf(buf2, "`%s`", foreign->foreign_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, ", "); } } buf2 += sprintf(buf2, ") REFERENCES `%s` (", foreign->referenced_table_name); /* Change the '/' in the table name to '.' */ for (i = ut_strlen(buf); i > 0; i--) { if (buf[i] == '/') { buf[i] = '.'; break; } } for (i = 0; i < foreign->n_fields; i++) { buf2 += sprintf(buf2, "`%s`", foreign->referenced_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, ", "); } } buf2 += sprintf(buf2, ")"); foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } mutex_exit(&(dict_sys->mutex)); buf[len - 1] = '\0'; ut_memcpy(str, buf, len); } /************************************************************************** Sprintfs to a string info on foreign keys of a table. */ void dict_print_info_on_foreign_keys( /*============================*/ ibool create_table_format, /* in: if TRUE then print in a format suitable to be inserted into a CREATE TABLE, otherwise in the format of SHOW TABLE STATUS */ char* str, /* in/out: pointer to a string */ ulint len, /* in: space in str available for info */ dict_table_t* table) /* in: table */ Loading @@ -2898,6 +3062,12 @@ dict_print_info_on_foreign_keys( char* buf2; char buf[10000]; if (create_table_format) { dict_print_info_on_foreign_keys_in_create_format( buf, str, len, table); return; } buf2 = buf; mutex_enter(&(dict_sys->mutex)); Loading @@ -2916,6 +3086,7 @@ dict_print_info_on_foreign_keys( for (i = 0; i < foreign->n_fields; i++) { buf2 += sprintf(buf2, "%s", foreign->foreign_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, " "); } Loading Loading
innobase/btr/btr0btr.c +13 −0 Original line number Diff line number Diff line Loading @@ -570,6 +570,19 @@ btr_page_get_father_for_rec( node_ptr = btr_cur_get_rec(&cursor); if (btr_node_ptr_get_child_page_no(node_ptr) != buf_frame_get_page_no(page)) { fprintf(stderr, "InnoDB: Corruption of an index tree: table %s, index %s,\n" "InnoDB: father ptr page no %lu, child page no %lu\n", (UT_LIST_GET_FIRST(tree->tree_indexes))->table_name, (UT_LIST_GET_FIRST(tree->tree_indexes))->name, btr_node_ptr_get_child_page_no(node_ptr), buf_frame_get_page_no(page)); page_rec_print(page_rec_get_next(page_get_infimum_rec(page))); page_rec_print(node_ptr); } ut_a(btr_node_ptr_get_child_page_no(node_ptr) == buf_frame_get_page_no(page)); mem_heap_free(heap); Loading
innobase/btr/btr0sea.c +1 −1 Original line number Diff line number Diff line Loading @@ -743,7 +743,7 @@ btr_search_guess_on_hash( #ifdef notdefined /* These lines of code can be used in a debug version to check correctness of the searched cursor position: */ the correctness of the searched cursor position: */ info->last_hash_succ = FALSE; Loading
innobase/buf/buf0buf.c +64 −18 Original line number Diff line number Diff line Loading @@ -220,6 +220,10 @@ buf_calc_page_checksum( { ulint checksum; /* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO are written outside the buffer pool to the first pages of data files, we have to skip them in page checksum calculation */ checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); + ut_fold_binary(page + FIL_PAGE_DATA, UNIV_PAGE_SIZE - FIL_PAGE_DATA Loading Loading @@ -279,6 +283,7 @@ buf_page_print( ut_sprintf_buf(buf, read_buf, UNIV_PAGE_SIZE); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n%s", UNIV_PAGE_SIZE, buf); Loading @@ -288,6 +293,7 @@ buf_page_print( checksum = buf_calc_page_checksum(read_buf); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Page checksum %lu stored checksum %lu\n", checksum, mach_read_from_4(read_buf + UNIV_PAGE_SIZE Loading Loading @@ -1358,21 +1364,51 @@ buf_page_io_complete( /*=================*/ buf_block_t* block) /* in: pointer to the block in question */ { dulint id; dict_index_t* index; dulint id; ulint io_type; ulint read_page_no; ut_ad(block); io_type = block->io_fix; if (io_type == BUF_IO_READ) { /* If this page is not uninitialized and not in the doublewrite buffer, then the page number should be the same as in block */ read_page_no = mach_read_from_4((block->frame) + FIL_PAGE_OFFSET); if (read_page_no != 0 && !trx_doublewrite_page_inside(read_page_no) && read_page_no != block->offset) { fprintf(stderr, "InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n", read_page_no, block->offset); } #ifdef notdefined if (block->offset != 0 && read_page_no == 0) { /* Check that the page is really uninited */ for (i = 0; i < UNIV_PAGE_SIZE; i++) { if (*((block->frame) + i) != '\0') { fprintf(stderr, "InnoDB: Error: page n:o in the page read in is 0, but page %lu is inited!\n", block->offset); break; } } } #endif /* From version 3.23.38 up we store the page checksum to the 4 upper bytes of the page end lsn field */ to the 4 first bytes of the page end lsn field */ if (buf_page_is_corrupted(block->frame)) { fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: Database page corruption on disk or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, Loading @@ -1381,7 +1417,7 @@ buf_page_io_complete( buf_page_print(block->frame); fprintf(stderr, "InnoDB: Database page corruption or a failed\n" "InnoDB: Database page corruption on disk or a failed\n" "InnoDB: file read of page %lu.\n", block->offset); fprintf(stderr, "InnoDB: You may have to recover from a backup.\n"); Loading @@ -1389,16 +1425,26 @@ buf_page_io_complete( "InnoDB: It is also possible that your operating\n" "InnoDB: system has corrupted its own file cache\n" "InnoDB: and rebooting your computer removes the\n" "InnoDB: error.\n"); "InnoDB: error.\n" "InnoDB: If the corrupt page is an index page\n" "InnoDB: you can also try to fix the corruption\n" "InnoDB: by dumping, dropping, and reimporting\n" "InnoDB: the corrupt table. You can use CHECK\n" "InnoDB: TABLE to scan your table for corruption.\n" "InnoDB: Look also at section 6.1 of\n" "InnoDB: http://www.innodb.com/ibman.html about\n" "InnoDB: forcing recovery.\n"); if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { fprintf(stderr, "InnoDB: Ending processing because of a corrupt database page.\n"); exit(1); } } if (recv_recovery_is_on()) { recv_recover_page(TRUE, block->frame, block->space, block->offset); recv_recover_page(FALSE, TRUE, block->frame, block->space, block->offset); } if (!recv_no_ibuf_operations) { Loading
innobase/buf/buf0flu.c +30 −17 Original line number Diff line number Diff line Loading @@ -327,6 +327,34 @@ buf_flush_post_to_doublewrite_buf( mutex_exit(&(trx_doublewrite->mutex)); } /************************************************************************ Initializes a page for writing to the tablespace. */ void buf_flush_init_for_writing( /*=======================*/ byte* page, /* in: page */ dulint newest_lsn, /* in: newest modification lsn to the page */ ulint space, /* in: space id */ ulint page_no) /* in: page number */ { /* Write the newest modification lsn to the page */ mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn); mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, newest_lsn); /* Write to the page the space id and page number */ mach_write_to_4(page + FIL_PAGE_SPACE, space); mach_write_to_4(page + FIL_PAGE_OFFSET, page_no); /* We overwrite the first 4 bytes of the end lsn field to store a page checksum */ mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, buf_calc_page_checksum(page)); } /************************************************************************ Does an asynchronous write of a buffer page. NOTE: in simulated aio and also when the doublewrite buffer is used, we must call Loading @@ -349,23 +377,8 @@ buf_flush_write_block_low( /* Force the log to the disk before writing the modified block */ log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS); #endif /* Write the newest modification lsn to the page */ mach_write_to_8(block->frame + FIL_PAGE_LSN, block->newest_modification); mach_write_to_8(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, block->newest_modification); /* Write to the page the space id and page number */ mach_write_to_4(block->frame + FIL_PAGE_SPACE, block->space); mach_write_to_4(block->frame + FIL_PAGE_OFFSET, block->offset); /* We overwrite the first 4 bytes of the end lsn field to store a page checksum */ mach_write_to_4(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN, buf_calc_page_checksum(block->frame)); buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); if (!trx_doublewrite) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, Loading
innobase/dict/dict0dict.c +185 −14 Original line number Diff line number Diff line Loading @@ -281,7 +281,8 @@ dict_table_autoinc_initialize( } /************************************************************************ Gets the next autoinc value, 0 if not yet initialized. */ Gets the next autoinc value, 0 if not yet initialized. If initialized, increments the counter by 1. */ ib_longlong dict_table_autoinc_get( Loading @@ -306,6 +307,32 @@ dict_table_autoinc_get( return(value); } /************************************************************************ Reads the autoinc counter value, 0 if not yet initialized. Does not increment the counter. */ ib_longlong dict_table_autoinc_read( /*====================*/ /* out: value of the counter */ dict_table_t* table) /* in: table */ { ib_longlong value; mutex_enter(&(table->autoinc_mutex)); if (!table->autoinc_inited) { value = 0; } else { value = table->autoinc; } mutex_exit(&(table->autoinc_mutex)); return(value); } /************************************************************************ Updates the autoinc counter if the value supplied is bigger than the current value. If not inited, does nothing. */ Loading Loading @@ -644,7 +671,10 @@ dict_table_rename_in_cache( /*=======================*/ /* out: TRUE if success */ dict_table_t* table, /* in: table */ char* new_name) /* in: new name */ char* new_name, /* in: new name */ ibool rename_also_foreigns)/* in: in ALTER TABLE we want to preserve the original table name in constraints which reference it */ { dict_foreign_t* foreign; dict_index_t* index; Loading Loading @@ -702,6 +732,41 @@ dict_table_rename_in_cache( index = dict_table_get_next_index(index); } if (!rename_also_foreigns) { /* In ALTER TABLE we think of the rename table operation in the direction table -> temporary table (#sql...) as dropping the table with the old name and creating a new with the new name. Thus we kind of drop the constraints from the dictionary cache here. The foreign key constraints will be inherited to the new table from the system tables through a call of dict_load_foreigns. */ /* Remove the foreign constraints from the cache */ foreign = UT_LIST_GET_LAST(table->foreign_list); while (foreign != NULL) { dict_foreign_remove_from_cache(foreign); foreign = UT_LIST_GET_LAST(table->foreign_list); } /* Reset table field in referencing constraints */ foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign != NULL) { foreign->referenced_table = NULL; foreign->referenced_index = NULL; foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } /* Make the list of referencing constraints empty */ UT_LIST_INIT(table->referenced_list); return(TRUE); } /* Update the table name fields in foreign constraints */ foreign = UT_LIST_GET_FIRST(table->foreign_list); Loading Loading @@ -768,8 +833,6 @@ dict_table_remove_from_cache( foreign = UT_LIST_GET_LAST(table->foreign_list); while (foreign != NULL) { ut_a(0 == ut_strcmp(foreign->foreign_table_name, table->name)); dict_foreign_remove_from_cache(foreign); foreign = UT_LIST_GET_LAST(table->foreign_list); } Loading @@ -779,8 +842,6 @@ dict_table_remove_from_cache( foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign != NULL) { ut_a(0 == ut_strcmp(foreign->referenced_table_name, table->name)); foreign->referenced_table = NULL; foreign->referenced_index = NULL; Loading Loading @@ -1630,6 +1691,7 @@ dict_foreign_add_to_cache( dict_table_t* ref_table; dict_foreign_t* for_in_cache = NULL; dict_index_t* index; ibool added_to_referenced_list = FALSE; ut_ad(mutex_own(&(dict_sys->mutex))); Loading Loading @@ -1673,6 +1735,7 @@ dict_foreign_add_to_cache( UT_LIST_ADD_LAST(referenced_list, ref_table->referenced_list, for_in_cache); added_to_referenced_list = TRUE; } if (for_in_cache->foreign_table == NULL && for_table) { Loading @@ -1683,6 +1746,12 @@ dict_foreign_add_to_cache( if (index == NULL) { if (for_in_cache == foreign) { if (added_to_referenced_list) { UT_LIST_REMOVE(referenced_list, ref_table->referenced_list, for_in_cache); } mem_heap_free(foreign->heap); } Loading Loading @@ -1802,9 +1871,14 @@ dict_scan_col( return(ptr); } if (*ptr == '`') { ptr++; } old_ptr = ptr; while (!isspace(*ptr) && *ptr != ',' && *ptr != ')') { while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') { ptr++; } Loading @@ -1825,6 +1899,10 @@ dict_scan_col( } } if (*ptr == '`') { ptr++; } return(ptr); } Loading Loading @@ -1855,9 +1933,13 @@ dict_scan_table_name( return(ptr); } if (*ptr == '`') { ptr++; } old_ptr = ptr; while (!isspace(*ptr) && *ptr != '(') { while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') { if (*ptr == '.') { dot_ptr = ptr; } Loading Loading @@ -1898,6 +1980,10 @@ dict_scan_table_name( *table = dict_table_get_low(second_table_name); if (*ptr == '`') { ptr++; } return(ptr); } Loading Loading @@ -1940,8 +2026,8 @@ dict_create_foreign_constraints( /*============================*/ /* out: error code or DB_SUCCESS */ trx_t* trx, /* in: transaction */ char* sql_string, /* in: table create statement where foreign keys are declared like: char* sql_string, /* in: table create or ALTER TABLE statement where foreign keys are declared like: FOREIGN KEY (a, b) REFERENCES table2(c, d), table2 can be written also with the database name before it: test.table2; the default Loading @@ -1967,10 +2053,11 @@ dict_create_foreign_constraints( if (table == NULL) { return(DB_ERROR); } loop: ptr = dict_scan_to(ptr, "FOREIGN"); if (*ptr == '\0' || dict_bracket_count(sql_string, ptr) != 1) { if (*ptr == '\0') { /* The following call adds the foreign key constraints to the data dictionary system tables on disk */ Loading Loading @@ -2883,12 +2970,89 @@ dict_field_print_low( printf(" %s", field->name); } /************************************************************************** Sprintfs to a string info on foreign keys of a table in a format suitable for CREATE TABLE. */ static void dict_print_info_on_foreign_keys_in_create_format( /*=============================================*/ char* buf, /* in: auxiliary buffer of 10000 chars */ char* str, /* in/out: pointer to a string */ ulint len, /* in: space in str available for info */ dict_table_t* table) /* in: table */ { dict_foreign_t* foreign; ulint i; char* buf2; buf2 = buf; mutex_enter(&(dict_sys->mutex)); foreign = UT_LIST_GET_FIRST(table->foreign_list); if (foreign == NULL) { mutex_exit(&(dict_sys->mutex)); return; } while (foreign != NULL) { buf2 += sprintf(buf2, ",\n FOREIGN KEY ("); for (i = 0; i < foreign->n_fields; i++) { buf2 += sprintf(buf2, "`%s`", foreign->foreign_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, ", "); } } buf2 += sprintf(buf2, ") REFERENCES `%s` (", foreign->referenced_table_name); /* Change the '/' in the table name to '.' */ for (i = ut_strlen(buf); i > 0; i--) { if (buf[i] == '/') { buf[i] = '.'; break; } } for (i = 0; i < foreign->n_fields; i++) { buf2 += sprintf(buf2, "`%s`", foreign->referenced_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, ", "); } } buf2 += sprintf(buf2, ")"); foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } mutex_exit(&(dict_sys->mutex)); buf[len - 1] = '\0'; ut_memcpy(str, buf, len); } /************************************************************************** Sprintfs to a string info on foreign keys of a table. */ void dict_print_info_on_foreign_keys( /*============================*/ ibool create_table_format, /* in: if TRUE then print in a format suitable to be inserted into a CREATE TABLE, otherwise in the format of SHOW TABLE STATUS */ char* str, /* in/out: pointer to a string */ ulint len, /* in: space in str available for info */ dict_table_t* table) /* in: table */ Loading @@ -2898,6 +3062,12 @@ dict_print_info_on_foreign_keys( char* buf2; char buf[10000]; if (create_table_format) { dict_print_info_on_foreign_keys_in_create_format( buf, str, len, table); return; } buf2 = buf; mutex_enter(&(dict_sys->mutex)); Loading @@ -2916,6 +3086,7 @@ dict_print_info_on_foreign_keys( for (i = 0; i < foreign->n_fields; i++) { buf2 += sprintf(buf2, "%s", foreign->foreign_col_names[i]); if (i + 1 < foreign->n_fields) { buf2 += sprintf(buf2, " "); } Loading