#include "univ.i"#include "data0data.h"#include "que0types.h"#include "dict0types.h"#include "trx0types.h"#include "row0types.h"#include "btr0pcur.h"Include dependency graph for row0mysql.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
| #define MYSQL_FETCH_CACHE_SIZE 8 |
Definition at line 505 of file row0mysql.h.
Referenced by row_create_prebuilt(), row_prebuilt_free(), row_search_for_mysql(), and row_sel_push_cache_row_for_mysql().
| #define MYSQL_FETCH_CACHE_THRESHOLD 4 |
| #define ROW_MYSQL_DUMMY_TEMPLATE 3 |
Definition at line 679 of file row0mysql.h.
Referenced by row_scan_and_check_index(), and row_search_for_mysql().
| #define ROW_MYSQL_NO_TEMPLATE 2 |
Definition at line 678 of file row0mysql.h.
| #define ROW_MYSQL_REC_FIELDS 1 |
Definition at line 677 of file row0mysql.h.
| #define ROW_MYSQL_WHOLE_ROW 0 |
| #define ROW_PREBUILT_ALLOCATED 78540783 |
Definition at line 509 of file row0mysql.h.
Referenced by row_create_prebuilt(), row_insert_for_mysql(), row_prebuilt_free(), row_search_for_mysql(), row_update_for_mysql(), and row_update_prebuilt_trx().
| #define ROW_PREBUILT_FETCH_MAGIC_N 465765687 |
Definition at line 674 of file row0mysql.h.
Referenced by row_prebuilt_free(), and row_sel_push_cache_row_for_mysql().
| #define ROW_PREBUILT_FREED 26423527 |
| #define ROW_READ_DID_SEMI_CONSISTENT 2 |
| #define ROW_READ_TRY_SEMI_CONSISTENT 1 |
| #define ROW_READ_WITH_LOCKS 0 |
Definition at line 687 of file row0mysql.h.
Referenced by row_create_prebuilt(), and row_search_for_mysql().
| #define ROW_RETRIEVE_ALL_COLS 2 |
Definition at line 684 of file row0mysql.h.
| #define ROW_RETRIEVE_PRIMARY_KEY 1 |
Definition at line 683 of file row0mysql.h.
| typedef struct mysql_row_templ_struct mysql_row_templ_t |
Definition at line 467 of file row0mysql.h.
| typedef struct row_prebuilt_struct row_prebuilt_t |
Definition at line 22 of file row0mysql.h.
| ulint row_check_table_for_mysql | ( | row_prebuilt_t * | prebuilt | ) |
Definition at line 3950 of file row0mysql.c.
References btr_search_validate(), btr_validate_tree(), DB_ERROR, DB_SUCCESS, dict_index_name_print(), dict_table_get_first_index(), dict_table_get_next_index(), dict_table_struct::ibd_file_missing, index(), trx_struct::isolation_level, kernel_mutex, mutex_enter, mutex_exit(), dict_table_struct::name, NULL, trx_struct::op_info, row_scan_and_check_index(), srv_fatal_semaphore_wait_threshold, row_prebuilt_struct::table, row_prebuilt_struct::trx, trx_is_interrupted(), TRX_ISO_REPEATABLE_READ, and ut_print_timestamp().
03952 : DB_ERROR or DB_SUCCESS */ 03953 row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL 03954 handle */ 03955 { 03956 dict_table_t* table = prebuilt->table; 03957 dict_index_t* index; 03958 ulint n_rows; 03959 ulint n_rows_in_table = ULINT_UNDEFINED; 03960 ulint ret = DB_SUCCESS; 03961 ulint old_isolation_level; 03962 03963 if (prebuilt->table->ibd_file_missing) { 03964 ut_print_timestamp(stderr); 03965 fprintf(stderr, " InnoDB: Error:\n" 03966 "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" 03967 "InnoDB: table %s does not exist.\n" 03968 "InnoDB: Have you deleted the .ibd file from the database directory under\n" 03969 "InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n" 03970 "InnoDB: Look from\n" 03971 "http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n" 03972 "InnoDB: how you can resolve the problem.\n", 03973 prebuilt->table->name); 03974 return(DB_ERROR); 03975 } 03976 03977 prebuilt->trx->op_info = "checking table"; 03978 03979 old_isolation_level = prebuilt->trx->isolation_level; 03980 03981 /* We must run the index record counts at an isolation level 03982 >= READ COMMITTED, because a dirty read can see a wrong number 03983 of records in some index; to play safe, we use always 03984 REPEATABLE READ here */ 03985 03986 prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; 03987 03988 /* Enlarge the fatal lock wait timeout during CHECK TABLE. */ 03989 mutex_enter(&kernel_mutex); 03990 srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ 03991 mutex_exit(&kernel_mutex); 03992 03993 index = dict_table_get_first_index(table); 03994 03995 while (index != NULL) { 03996 /* fputs("Validating index ", stderr); 03997 ut_print_name(stderr, trx, FALSE, index->name); 03998 putc('\n', stderr); */ 03999 04000 if (!btr_validate_tree(index->tree, prebuilt->trx)) { 04001 ret = DB_ERROR; 04002 } else { 04003 if (!row_scan_and_check_index(prebuilt, 04004 index, &n_rows)) { 04005 ret = DB_ERROR; 04006 } 04007 04008 if (trx_is_interrupted(prebuilt->trx)) { 04009 break; 04010 } 04011 04012 /* fprintf(stderr, "%lu entries in index %s\n", n_rows, 04013 index->name); */ 04014 04015 if (index == dict_table_get_first_index(table)) { 04016 n_rows_in_table = n_rows; 04017 } else if (n_rows != n_rows_in_table) { 04018 04019 ret = DB_ERROR; 04020 04021 fputs("Error: ", stderr); 04022 dict_index_name_print(stderr, 04023 prebuilt->trx, index); 04024 fprintf(stderr, 04025 " contains %lu entries, should be %lu\n", 04026 (ulong) n_rows, 04027 (ulong) n_rows_in_table); 04028 } 04029 } 04030 04031 index = dict_table_get_next_index(index); 04032 } 04033 04034 /* Restore the original isolation level */ 04035 prebuilt->trx->isolation_level = old_isolation_level; 04036 04037 /* We validate also the whole adaptive hash index for all tables 04038 at every CHECK TABLE */ 04039 04040 if (!btr_search_validate()) { 04041 04042 ret = DB_ERROR; 04043 } 04044 04045 /* Restore the fatal lock wait timeout after CHECK TABLE. */ 04046 mutex_enter(&kernel_mutex); 04047 srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */ 04048 mutex_exit(&kernel_mutex); 04049 04050 prebuilt->trx->op_info = ""; 04051 04052 return(ret); 04053 }
Here is the call graph for this function:

| int row_create_index_for_mysql | ( | dict_index_t * | index, | |
| trx_t * | trx, | |||
| const ulint * | field_lengths | |||
| ) |
Definition at line 1994 of file row0mysql.c.
References DB_COL_APPEARS_TWICE_IN_INDEX, DB_SUCCESS, DB_TOO_BIG_RECORD, dict_index_get_n_fields(), dict_index_get_nth_field(), dict_index_name_print(), DICT_MAX_INDEX_COL_LEN, trx_struct::dict_operation, dict_operation_lock, dict_sys, err, trx_struct::error_state, FALSE, ind_create_graph_create(), index(), mem_heap_create, dict_sys_struct::mutex, trx_struct::mysql_thread_id, name, NULL, trx_struct::op_info, os_thread_get_curr_id(), pars_complete_graph_for_exec(), dict_field_struct::prefix_len, que_fork_start_command(), que_graph_free(), que_node_get_parent(), que_run_threads(), row_drop_table_for_mysql(), RW_LOCK_EX, TRUE, trx_general_rollback_for_mysql(), trx_start_if_not_started(), ut_a, ut_ad, ut_max(), ut_print_name(), ut_print_timestamp(), and ut_strcmp().
01996 : error number or DB_SUCCESS */ 01997 dict_index_t* index, /* in: index definition */ 01998 trx_t* trx, /* in: transaction handle */ 01999 const ulint* field_lengths) /* in: if not NULL, must contain 02000 dict_index_get_n_fields(index) 02001 actual field lengths for the 02002 index columns, which are 02003 then checked for not being too 02004 large. */ 02005 { 02006 ind_node_t* node; 02007 mem_heap_t* heap; 02008 que_thr_t* thr; 02009 ulint err; 02010 ulint i, j; 02011 ulint len; 02012 02013 #ifdef UNIV_SYNC_DEBUG 02014 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); 02015 ut_ad(mutex_own(&(dict_sys->mutex))); 02016 #endif /* UNIV_SYNC_DEBUG */ 02017 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 02018 02019 trx->op_info = "creating index"; 02020 02021 trx_start_if_not_started(trx); 02022 02023 /* Check that the same column does not appear twice in the index. 02024 Starting from 4.0.14, InnoDB should be able to cope with that, but 02025 safer not to allow them. */ 02026 02027 for (i = 0; i < dict_index_get_n_fields(index); i++) { 02028 for (j = 0; j < i; j++) { 02029 if (0 == ut_strcmp( 02030 dict_index_get_nth_field(index, j)->name, 02031 dict_index_get_nth_field(index, i)->name)) { 02032 02033 ut_print_timestamp(stderr); 02034 02035 fputs(" InnoDB: Error: column ", stderr); 02036 ut_print_name(stderr, trx, FALSE, 02037 dict_index_get_nth_field(index, i)->name); 02038 fputs(" appears twice in ", stderr); 02039 dict_index_name_print(stderr, trx, index); 02040 fputs("\n" 02041 "InnoDB: This is not allowed in InnoDB.\n", 02042 stderr); 02043 02044 err = DB_COL_APPEARS_TWICE_IN_INDEX; 02045 02046 goto error_handling; 02047 } 02048 } 02049 02050 /* Check also that prefix_len and actual length 02051 < DICT_MAX_INDEX_COL_LEN */ 02052 02053 len = dict_index_get_nth_field(index, i)->prefix_len; 02054 02055 if (field_lengths) { 02056 len = ut_max(len, field_lengths[i]); 02057 } 02058 02059 if (len >= DICT_MAX_INDEX_COL_LEN) { 02060 err = DB_TOO_BIG_RECORD; 02061 02062 goto error_handling; 02063 } 02064 } 02065 02066 if (row_mysql_is_recovered_tmp_table(index->table_name)) { 02067 02068 return(DB_SUCCESS); 02069 } 02070 02071 heap = mem_heap_create(512); 02072 02073 trx->dict_operation = TRUE; 02074 02075 /* Note that the space id where we store the index is inherited from 02076 the table in dict_build_index_def_step() in dict0crea.c. */ 02077 02078 node = ind_create_graph_create(index, heap); 02079 02080 thr = pars_complete_graph_for_exec(node, trx, heap); 02081 02082 ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); 02083 que_run_threads(thr); 02084 02085 err = trx->error_state; 02086 02087 que_graph_free((que_t*) que_node_get_parent(thr)); 02088 02089 error_handling: 02090 if (err != DB_SUCCESS) { 02091 /* We have special error handling here */ 02092 02093 trx->error_state = DB_SUCCESS; 02094 02095 trx_general_rollback_for_mysql(trx, FALSE, NULL); 02096 02097 row_drop_table_for_mysql(index->table_name, trx, FALSE); 02098 02099 trx->error_state = DB_SUCCESS; 02100 } 02101 02102 trx->op_info = ""; 02103 02104 return((int) err); 02105 }
Here is the call graph for this function:

| row_prebuilt_t* row_create_prebuilt | ( | dict_table_t * | table | ) |
Definition at line 584 of file row0mysql.c.
References row_prebuilt_struct::blob_heap, btr_pcur_create_for_mysql(), row_prebuilt_struct::clust_pcur, row_prebuilt_struct::clust_ref, dict_index_copy_types(), dict_index_get_n_unique(), dict_table_get_first_index(), dict_table_get_n_cols(), dtuple_create(), FALSE, row_prebuilt_struct::fetch_cache, row_prebuilt_struct::heap, row_prebuilt_struct::index, row_prebuilt_struct::ins_graph, row_prebuilt_struct::ins_node, row_prebuilt_struct::ins_upd_rec_buff, LOCK_NONE, row_prebuilt_struct::magic_n, row_prebuilt_struct::magic_n2, mem_heap_alloc(), mem_heap_create, MYSQL_FETCH_CACHE_SIZE, row_prebuilt_struct::mysql_has_locked, row_prebuilt_struct::mysql_template, row_prebuilt_struct::n_fetch_cached, dict_index_struct::n_fields, row_prebuilt_struct::n_template, NULL, row_prebuilt_struct::old_vers_heap, row_prebuilt_struct::pcur, ROW_PREBUILT_ALLOCATED, row_prebuilt_struct::row_read_type, ROW_READ_WITH_LOCKS, row_prebuilt_struct::search_tuple, row_prebuilt_struct::sel_graph, row_prebuilt_struct::select_lock_type, row_prebuilt_struct::sql_stat_start, row_prebuilt_struct::stored_select_lock_type, row_prebuilt_struct::table, TRUE, row_prebuilt_struct::trx, row_prebuilt_struct::upd_graph, row_prebuilt_struct::upd_node, row_prebuilt_struct::used_in_HANDLER, and ut_a.
00586 : a prebuilt struct */ 00587 dict_table_t* table) /* in: Innobase table handle */ 00588 { 00589 row_prebuilt_t* prebuilt; 00590 mem_heap_t* heap; 00591 dict_index_t* clust_index; 00592 dtuple_t* ref; 00593 ulint ref_len; 00594 ulint i; 00595 00596 heap = mem_heap_create(128); 00597 00598 prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t)); 00599 00600 prebuilt->magic_n = ROW_PREBUILT_ALLOCATED; 00601 prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED; 00602 00603 prebuilt->table = table; 00604 00605 prebuilt->trx = NULL; 00606 00607 prebuilt->sql_stat_start = TRUE; 00608 00609 prebuilt->mysql_has_locked = FALSE; 00610 00611 prebuilt->index = NULL; 00612 00613 prebuilt->used_in_HANDLER = FALSE; 00614 00615 prebuilt->n_template = 0; 00616 prebuilt->mysql_template = NULL; 00617 00618 prebuilt->heap = heap; 00619 prebuilt->ins_node = NULL; 00620 00621 prebuilt->ins_upd_rec_buff = NULL; 00622 00623 prebuilt->upd_node = NULL; 00624 prebuilt->ins_graph = NULL; 00625 prebuilt->upd_graph = NULL; 00626 00627 prebuilt->pcur = btr_pcur_create_for_mysql(); 00628 prebuilt->clust_pcur = btr_pcur_create_for_mysql(); 00629 00630 prebuilt->select_lock_type = LOCK_NONE; 00631 prebuilt->stored_select_lock_type = 99999999; 00632 00633 prebuilt->row_read_type = ROW_READ_WITH_LOCKS; 00634 00635 prebuilt->sel_graph = NULL; 00636 00637 prebuilt->search_tuple = dtuple_create(heap, 00638 2 * dict_table_get_n_cols(table)); 00639 00640 clust_index = dict_table_get_first_index(table); 00641 00642 /* Make sure that search_tuple is long enough for clustered index */ 00643 ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields); 00644 00645 ref_len = dict_index_get_n_unique(clust_index); 00646 00647 ref = dtuple_create(heap, ref_len); 00648 00649 dict_index_copy_types(ref, clust_index, ref_len); 00650 00651 prebuilt->clust_ref = ref; 00652 00653 for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) { 00654 prebuilt->fetch_cache[i] = NULL; 00655 } 00656 00657 prebuilt->n_fetch_cached = 0; 00658 00659 prebuilt->blob_heap = NULL; 00660 00661 prebuilt->old_vers_heap = NULL; 00662 00663 return(prebuilt); 00664 }
Here is the call graph for this function:

| int row_create_table_for_mysql | ( | dict_table_t * | table, | |
| trx_t * | trx | |||
| ) |
Definition at line 1782 of file row0mysql.c.
References DB_DUPLICATE_KEY, DB_ERROR, DB_OUT_OF_FILE_SPACE, DB_SUCCESS, dict_col_name_is_reserved(), dict_mem_table_free(), trx_struct::dict_operation, dict_operation_lock, trx_struct::dict_operation_lock_mode, dict_sys, dict_table_get_low(), dict_table_get_n_user_cols(), dict_table_get_nth_col(), err, trx_struct::error_state, FALSE, mem_heap_create, memcmp(), dict_sys_struct::mutex, trx_struct::mysql_thread_id, dict_table_struct::name, NULL, trx_struct::op_info, os_event_set(), os_thread_get_curr_id(), pars_complete_graph_for_exec(), que_fork_start_command(), que_graph_free(), que_node_get_parent(), que_run_threads(), row_drop_table_for_mysql(), row_mysql_is_system_table(), row_mysql_recover_tmp_table(), RW_LOCK_EX, RW_X_LATCH, srv_created_new_raw, srv_lock_timeout_thread_event, srv_print_innodb_lock_monitor, srv_print_innodb_monitor, srv_print_innodb_table_monitor, srv_print_innodb_tablespace_monitor, strchr(), strlen(), tab_create_graph_create(), TRUE, trx_commit_for_mysql(), trx_general_rollback_for_mysql(), trx_start_if_not_started(), ut_a, ut_ad, ut_print_name(), and ut_print_timestamp().
01784 : error code or DB_SUCCESS */ 01785 dict_table_t* table, /* in: table definition */ 01786 trx_t* trx) /* in: transaction handle */ 01787 { 01788 tab_node_t* node; 01789 mem_heap_t* heap; 01790 que_thr_t* thr; 01791 const char* table_name; 01792 ulint table_name_len; 01793 ulint err; 01794 ulint i; 01795 01796 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 01797 #ifdef UNIV_SYNC_DEBUG 01798 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); 01799 ut_ad(mutex_own(&(dict_sys->mutex))); 01800 #endif /* UNIV_SYNC_DEBUG */ 01801 ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); 01802 01803 if (srv_created_new_raw) { 01804 fputs( 01805 "InnoDB: A new raw disk partition was initialized or\n" 01806 "InnoDB: innodb_force_recovery is on: we do not allow\n" 01807 "InnoDB: database modifications by the user. Shut down\n" 01808 "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" 01809 "InnoDB: with raw, and innodb_force_... is removed.\n", 01810 stderr); 01811 01812 dict_mem_table_free(table); 01813 trx_commit_for_mysql(trx); 01814 01815 return(DB_ERROR); 01816 } 01817 01818 trx->op_info = "creating table"; 01819 01820 if (row_mysql_is_system_table(table->name)) { 01821 01822 fprintf(stderr, 01823 "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" 01824 "InnoDB: MySQL system tables must be of the MyISAM type!\n", 01825 table->name); 01826 01827 dict_mem_table_free(table); 01828 trx_commit_for_mysql(trx); 01829 01830 return(DB_ERROR); 01831 } 01832 01833 /* Check that no reserved column names are used. */ 01834 for (i = 0; i < dict_table_get_n_user_cols(table); i++) { 01835 dict_col_t* col = dict_table_get_nth_col(table, i); 01836 01837 if (dict_col_name_is_reserved(col->name)) { 01838 01839 dict_mem_table_free(table); 01840 trx_commit_for_mysql(trx); 01841 01842 return(DB_ERROR); 01843 } 01844 } 01845 01846 trx_start_if_not_started(trx); 01847 01848 if (row_mysql_is_recovered_tmp_table(table->name)) { 01849 01850 /* MySQL prevents accessing of tables whose name begins 01851 with #sql, that is temporary tables. If mysqld crashes in 01852 the middle of an ALTER TABLE, we may get an orphaned 01853 #sql-table in the tablespace. We have here a special 01854 mechanism to recover such tables by renaming them to 01855 rsql... */ 01856 01857 return(row_mysql_recover_tmp_table(table, trx)); 01858 } 01859 01860 /* The table name is prefixed with the database name and a '/'. 01861 Certain table names starting with 'innodb_' have their special 01862 meaning regardless of the database name. Thus, we need to 01863 ignore the database name prefix in the comparisons. */ 01864 table_name = strchr(table->name, '/'); 01865 ut_a(table_name); 01866 table_name++; 01867 table_name_len = strlen(table_name) + 1; 01868 01869 if (table_name_len == sizeof S_innodb_monitor 01870 && !memcmp(table_name, S_innodb_monitor, 01871 sizeof S_innodb_monitor)) { 01872 01873 /* Table equals "innodb_monitor": 01874 start monitor prints */ 01875 01876 srv_print_innodb_monitor = TRUE; 01877 01878 /* The lock timeout monitor thread also takes care 01879 of InnoDB monitor prints */ 01880 01881 os_event_set(srv_lock_timeout_thread_event); 01882 } else if (table_name_len == sizeof S_innodb_lock_monitor 01883 && !memcmp(table_name, S_innodb_lock_monitor, 01884 sizeof S_innodb_lock_monitor)) { 01885 01886 srv_print_innodb_monitor = TRUE; 01887 srv_print_innodb_lock_monitor = TRUE; 01888 os_event_set(srv_lock_timeout_thread_event); 01889 } else if (table_name_len == sizeof S_innodb_tablespace_monitor 01890 && !memcmp(table_name, S_innodb_tablespace_monitor, 01891 sizeof S_innodb_tablespace_monitor)) { 01892 01893 srv_print_innodb_tablespace_monitor = TRUE; 01894 os_event_set(srv_lock_timeout_thread_event); 01895 } else if (table_name_len == sizeof S_innodb_table_monitor 01896 && !memcmp(table_name, S_innodb_table_monitor, 01897 sizeof S_innodb_table_monitor)) { 01898 01899 srv_print_innodb_table_monitor = TRUE; 01900 os_event_set(srv_lock_timeout_thread_event); 01901 } else if (table_name_len == sizeof S_innodb_mem_validate 01902 && !memcmp(table_name, S_innodb_mem_validate, 01903 sizeof S_innodb_mem_validate)) { 01904 /* We define here a debugging feature intended for 01905 developers */ 01906 01907 fputs("Validating InnoDB memory:\n" 01908 "to use this feature you must compile InnoDB with\n" 01909 "UNIV_MEM_DEBUG defined in univ.i and the server must be\n" 01910 "quiet because allocation from a mem heap is not protected\n" 01911 "by any semaphore.\n", stderr); 01912 #ifdef UNIV_MEM_DEBUG 01913 ut_a(mem_validate()); 01914 fputs("Memory validated\n", stderr); 01915 #else /* UNIV_MEM_DEBUG */ 01916 fputs("Memory NOT validated (recompile with UNIV_MEM_DEBUG)\n", 01917 stderr); 01918 #endif /* UNIV_MEM_DEBUG */ 01919 } 01920 01921 heap = mem_heap_create(512); 01922 01923 trx->dict_operation = TRUE; 01924 01925 node = tab_create_graph_create(table, heap); 01926 01927 thr = pars_complete_graph_for_exec(node, trx, heap); 01928 01929 ut_a(thr == que_fork_start_command(que_node_get_parent(thr))); 01930 que_run_threads(thr); 01931 01932 err = trx->error_state; 01933 01934 if (err != DB_SUCCESS) { 01935 /* We have special error handling here */ 01936 01937 trx->error_state = DB_SUCCESS; 01938 01939 trx_general_rollback_for_mysql(trx, FALSE, NULL); 01940 01941 if (err == DB_OUT_OF_FILE_SPACE) { 01942 ut_print_timestamp(stderr); 01943 01944 fputs(" InnoDB: Warning: cannot create table ", 01945 stderr); 01946 ut_print_name(stderr, trx, TRUE, table->name); 01947 fputs(" because tablespace full\n", stderr); 01948 01949 if (dict_table_get_low(table->name)) { 01950 01951 row_drop_table_for_mysql(table->name, trx, 01952 FALSE); 01953 } 01954 01955 } else if (err == DB_DUPLICATE_KEY) { 01956 ut_print_timestamp(stderr); 01957 01958 fputs(" InnoDB: Error: table ", stderr); 01959 ut_print_name(stderr, trx, TRUE, table->name); 01960 fputs(" already exists in InnoDB internal\n" 01961 "InnoDB: data dictionary. Have you deleted the .frm file\n" 01962 "InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n" 01963 "InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n" 01964 "InnoDB: See the Restrictions section of the InnoDB manual.\n" 01965 "InnoDB: You can drop the orphaned table inside InnoDB by\n" 01966 "InnoDB: creating an InnoDB table with the same name in another\n" 01967 "InnoDB: database and copying the .frm file to the current database.\n" 01968 "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" 01969 "InnoDB: succeed.\n" 01970 "InnoDB: You can look for further help from\n" 01971 "InnoDB: http://dev.mysql.com/doc/mysql/en/" 01972 "InnoDB_troubleshooting_datadict.html\n", stderr); 01973 } 01974 01975 /* We may also get err == DB_ERROR if the .ibd file for the 01976 table already exists */ 01977 01978 trx->error_state = DB_SUCCESS; 01979 } 01980 01981 que_graph_free((que_t*) que_node_get_parent(thr)); 01982 01983 trx->op_info = ""; 01984 01985 return((int) err); 01986 }
Here is the call graph for this function:

| upd_node_t* row_create_update_node_for_mysql | ( | dict_table_t * | table, | |
| mem_heap_t * | heap | |||
| ) |
Definition at line 1219 of file row0mysql.c.
References btr_pcur_create_for_mysql(), upd_node_struct::cmpl_info, upd_node_struct::col_assign_list, upd_node_struct::columns, dict_table_get_n_cols(), FALSE, upd_node_struct::has_clust_rec_x_lock, upd_node_struct::in_mysql_interface, upd_node_struct::is_delete, NULL, upd_node_struct::pcur, upd_node_struct::searched_update, upd_node_struct::select, upd_node_struct::select_will_do_update, upd_node_struct::table, upd_node_struct::table_sym, TRUE, upd_create(), upd_node_create(), upd_node_struct::update, upd_node_struct::update_n_fields, and UT_LIST_INIT.
Referenced by row_get_prebuilt_update_vector(), and row_ins_foreign_check_on_constraint().
01221 : update node */ 01222 dict_table_t* table, /* in: table to update */ 01223 mem_heap_t* heap) /* in: mem heap from which allocated */ 01224 { 01225 upd_node_t* node; 01226 01227 node = upd_node_create(heap); 01228 01229 node->in_mysql_interface = TRUE; 01230 node->is_delete = FALSE; 01231 node->searched_update = FALSE; 01232 node->select_will_do_update = FALSE; 01233 node->select = NULL; 01234 node->pcur = btr_pcur_create_for_mysql(); 01235 node->table = table; 01236 01237 node->update = upd_create(dict_table_get_n_cols(table), heap); 01238 01239 node->update_n_fields = dict_table_get_n_cols(table); 01240 01241 UT_LIST_INIT(node->columns); 01242 node->has_clust_rec_x_lock = TRUE; 01243 node->cmpl_info = 0; 01244 01245 node->table_sym = NULL; 01246 node->col_assign_list = NULL; 01247 01248 return(node); 01249 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int row_discard_tablespace_for_mysql | ( | const char * | name, | |
| trx_t * | trx | |||
| ) |
Definition at line 2380 of file row0mysql.c.
References trx_struct::check_foreigns, DB_CANNOT_DROP_CONSTRAINT, DB_ERROR, DB_SUCCESS, DB_TABLE_NOT_FOUND, dict_foreign_err_file, dict_foreign_err_mutex, dict_hdr_get_new_id(), DICT_HDR_TABLE_ID, dict_table_change_id_in_cache(), dict_table_get_low(), err, trx_struct::error_state, FALSE, fil_discard_tablespace(), dict_foreign_struct::foreign_table, dict_foreign_struct::foreign_table_name, dict_table_struct::ibd_file_missing, info, lock_reset_all_on_table(), mutex_enter, mutex_exit(), trx_struct::mysql_thread_id, dict_table_struct::n_foreign_key_checks_running, dict_table_struct::name, NULL, trx_struct::op_info, os_thread_get_curr_id(), pars_info_add_dulint_literal(), pars_info_add_str_literal(), pars_info_create(), que_eval_sql(), dict_table_struct::referenced_list, row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary(), dict_table_struct::space, dict_table_struct::tablespace_discarded, TRUE, trx_commit_for_mysql(), trx_general_rollback_for_mysql(), trx_start_if_not_started(), ut_ad, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, ut_print_name(), and ut_print_timestamp().
02382 : error code or DB_SUCCESS */ 02383 const char* name, /* in: table name */ 02384 trx_t* trx) /* in: transaction handle */ 02385 { 02386 dict_foreign_t* foreign; 02387 dulint new_id; 02388 dict_table_t* table; 02389 ibool success; 02390 ulint err; 02391 pars_info_t* info = NULL; 02392 02393 /* How do we prevent crashes caused by ongoing operations on the table? Old 02394 operations could try to access non-existent pages. 02395 02396 1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock 02397 on the table before we can do DISCARD TABLESPACE. Then there are no running 02398 queries on the table. 02399 2) Purge and rollback: we assign a new table id for the table. Since purge and 02400 rollback look for the table based on the table id, they see the table as 02401 'dropped' and discard their operations. 02402 3) Insert buffer: we remove all entries for the tablespace in the insert 02403 buffer tree; as long as the tablespace mem object does not exist, ongoing 02404 insert buffer page merges are discarded in buf0rea.c. If we recreate the 02405 tablespace mem object with IMPORT TABLESPACE later, then the tablespace will 02406 have the same id, but the tablespace_version field in the mem object is 02407 different, and ongoing old insert buffer page merges get discarded. 02408 4) Linear readahead and random readahead: we use the same method as in 3) to 02409 discard ongoing operations. 02410 5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we 02411 do not allow the discard. We also reserve the data dictionary latch. */ 02412 02413 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 02414 02415 trx->op_info = "discarding tablespace"; 02416 trx_start_if_not_started(trx); 02417 02418 /* Serialize data dictionary operations with dictionary mutex: 02419 no deadlocks can occur then in these operations */ 02420 02421 row_mysql_lock_data_dictionary(trx); 02422 02423 table = dict_table_get_low(name); 02424 02425 if (!table) { 02426 err = DB_TABLE_NOT_FOUND; 02427 02428 goto funct_exit; 02429 } 02430 02431 if (table->space == 0) { 02432 ut_print_timestamp(stderr); 02433 fputs(" InnoDB: Error: table ", stderr); 02434 ut_print_name(stderr, trx, TRUE, name); 02435 fputs("\n" 02436 "InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr); 02437 err = DB_ERROR; 02438 02439 goto funct_exit; 02440 } 02441 02442 if (table->n_foreign_key_checks_running > 0) { 02443 02444 ut_print_timestamp(stderr); 02445 fputs(" InnoDB: You are trying to DISCARD table ", stderr); 02446 ut_print_name(stderr, trx, TRUE, table->name); 02447 fputs("\n" 02448 "InnoDB: though there is a foreign key check running on it.\n" 02449 "InnoDB: Cannot discard the table.\n", 02450 stderr); 02451 02452 err = DB_ERROR; 02453 02454 goto funct_exit; 02455 } 02456 02457 /* Check if the table is referenced by foreign key constraints from 02458 some other table (not the table itself) */ 02459 02460 foreign = UT_LIST_GET_FIRST(table->referenced_list); 02461 02462 while (foreign && foreign->foreign_table == table) { 02463 foreign = UT_LIST_GET_NEXT(referenced_list, foreign); 02464 } 02465 02466 if (foreign && trx->check_foreigns) { 02467 02468 FILE* ef = dict_foreign_err_file; 02469 02470 /* We only allow discarding a referenced table if 02471 FOREIGN_KEY_CHECKS is set to 0 */ 02472 02473 err = DB_CANNOT_DROP_CONSTRAINT; 02474 02475 mutex_enter(&dict_foreign_err_mutex); 02476 rewind(ef); 02477 ut_print_timestamp(ef); 02478 02479 fputs(" Cannot DISCARD table ", ef); 02480 ut_print_name(ef, trx, TRUE, name); 02481 fputs("\n" 02482 "because it is referenced by ", ef); 02483 ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); 02484 putc('\n', ef); 02485 mutex_exit(&dict_foreign_err_mutex); 02486 02487 goto funct_exit; 02488 } 02489 02490 new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); 02491 02492 /* Remove any locks there are on the table or its records */ 02493 lock_reset_all_on_table(table); 02494 02495 info = pars_info_create(); 02496 02497 pars_info_add_str_literal(info, "table_name", name); 02498 pars_info_add_dulint_literal(info, "new_id", new_id); 02499 02500 err = que_eval_sql(info, 02501 "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n" 02502 "old_id CHAR;\n" 02503 "BEGIN\n" 02504 "SELECT ID INTO old_id\n" 02505 "FROM SYS_TABLES\n" 02506 "WHERE NAME = :table_name\n" 02507 "LOCK IN SHARE MODE;\n" 02508 "IF (SQL % NOTFOUND) THEN\n" 02509 " COMMIT WORK;\n" 02510 " RETURN;\n" 02511 "END IF;\n" 02512 "UPDATE SYS_TABLES SET ID = :new_id\n" 02513 " WHERE ID = old_id;\n" 02514 "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n" 02515 " WHERE TABLE_ID = old_id;\n" 02516 "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n" 02517 " WHERE TABLE_ID = old_id;\n" 02518 "COMMIT WORK;\n" 02519 "END;\n" 02520 , FALSE, trx); 02521 02522 if (err != DB_SUCCESS) { 02523 trx->error_state = DB_SUCCESS; 02524 trx_general_rollback_for_mysql(trx, FALSE, NULL); 02525 trx->error_state = DB_SUCCESS; 02526 } else { 02527 dict_table_change_id_in_cache(table, new_id); 02528 02529 success = fil_discard_tablespace(table->space); 02530 02531 if (!success) { 02532 trx->error_state = DB_SUCCESS; 02533 trx_general_rollback_for_mysql(trx, FALSE, NULL); 02534 trx->error_state = DB_SUCCESS; 02535 02536 err = DB_ERROR; 02537 } else { 02538 /* Set the flag which tells that now it is legal to 02539 IMPORT a tablespace for this table */ 02540 table->tablespace_discarded = TRUE; 02541 table->ibd_file_missing = TRUE; 02542 } 02543 } 02544 02545 funct_exit: 02546 trx_commit_for_mysql(trx); 02547 02548 row_mysql_unlock_data_dictionary(trx); 02549 02550 trx->op_info = ""; 02551 02552 return((int) err); 02553 }
Here is the call graph for this function:

| int row_drop_database_for_mysql | ( | const char * | name, | |
| trx_t * | trx | |||
| ) |
Definition at line 3337 of file row0mysql.c.
References DB_SUCCESS, dict_get_first_table_name_in_db(), dict_table_get_low(), err, mem_free, memcmp(), trx_struct::mysql_thread_id, dict_table_struct::n_mysql_handles_opened, NULL, trx_struct::op_info, os_thread_get_curr_id(), os_thread_sleep(), row_drop_table_for_mysql(), row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary(), strlen(), TRUE, trx_commit_for_mysql(), trx_start_if_not_started(), ut_a, ut_ad, ut_print_name(), and ut_print_timestamp().
03339 : error code or DB_SUCCESS */ 03340 const char* name, /* in: database name which ends to '/' */ 03341 trx_t* trx) /* in: transaction handle */ 03342 { 03343 dict_table_t* table; 03344 char* table_name; 03345 int err = DB_SUCCESS; 03346 ulint namelen = strlen(name); 03347 03348 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 03349 ut_a(name != NULL); 03350 ut_a(name[namelen - 1] == '/'); 03351 03352 trx->op_info = "dropping database"; 03353 03354 trx_start_if_not_started(trx); 03355 loop: 03356 row_mysql_lock_data_dictionary(trx); 03357 03358 while ((table_name = dict_get_first_table_name_in_db(name))) { 03359 ut_a(memcmp(table_name, name, namelen) == 0); 03360 03361 table = dict_table_get_low(table_name); 03362 03363 ut_a(table); 03364 03365 /* Wait until MySQL does not have any queries running on 03366 the table */ 03367 03368 if (table->n_mysql_handles_opened > 0) { 03369 row_mysql_unlock_data_dictionary(trx); 03370 03371 ut_print_timestamp(stderr); 03372 fputs( 03373 " InnoDB: Warning: MySQL is trying to drop database ", stderr); 03374 ut_print_name(stderr, trx, TRUE, name); 03375 fputs("\n" 03376 "InnoDB: though there are still open handles to table ", stderr); 03377 ut_print_name(stderr, trx, TRUE, table_name); 03378 fputs(".\n", stderr); 03379 03380 os_thread_sleep(1000000); 03381 03382 mem_free(table_name); 03383 03384 goto loop; 03385 } 03386 03387 err = row_drop_table_for_mysql(table_name, trx, TRUE); 03388 03389 mem_free(table_name); 03390 03391 if (err != DB_SUCCESS) { 03392 fputs("InnoDB: DROP DATABASE ", stderr); 03393 ut_print_name(stderr, trx, TRUE, name); 03394 fprintf(stderr, " failed with error %lu for table ", 03395 (ulint) err); 03396 ut_print_name(stderr, trx, TRUE, table_name); 03397 putc('\n', stderr); 03398 break; 03399 } 03400 } 03401 03402 trx_commit_for_mysql(trx); 03403 03404 row_mysql_unlock_data_dictionary(trx); 03405 03406 trx->op_info = ""; 03407 03408 return(err); 03409 }
Here is the call graph for this function:

| int row_drop_table_for_mysql | ( | const char * | name, | |
| trx_t * | trx, | |||
| ibool | drop_db | |||
| ) |
Definition at line 2956 of file row0mysql.c.
References trx_struct::check_foreigns, DB_CANNOT_DROP_CONSTRAINT, DB_ERROR, DB_MUST_GET_MORE_FILE_SPACE, DB_OUT_OF_FILE_SPACE, DB_SUCCESS, DB_TABLE_NOT_FOUND, dict_foreign_err_file, dict_foreign_err_mutex, dict_load_table(), trx_struct::dict_operation, dict_operation_lock, trx_struct::dict_operation_lock_mode, dict_sys, dict_table_get_low(), dict_table_remove_from_cache(), dict_tables_have_same_db(), dict_table_struct::dir_path_of_temp_table, err, FALSE, fil_delete_tablespace(), fil_space_for_table_exists_in_mem(), dict_foreign_struct::foreign_table, dict_foreign_struct::foreign_table_name, dict_table_struct::id, info, lock_reset_all_on_table(), mem_free, mem_strdup(), memcmp(), dict_sys_struct::mutex, mutex_enter, mutex_exit(), dict_table_struct::n_foreign_key_checks_running, dict_table_struct::n_mysql_handles_opened, dict_table_struct::name, NULL, trx_struct::op_info, pars_info_add_str_literal(), pars_info_create(), que_eval_sql(), dict_table_struct::referenced_list, row_add_table_to_background_drop_list(), row_mysql_handle_errors(), row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary(), RW_LOCK_EX, RW_X_LATCH, dict_table_struct::space, srv_created_new_raw, srv_print_innodb_lock_monitor, srv_print_innodb_monitor, srv_print_innodb_table_monitor, srv_print_innodb_tablespace_monitor, srv_wake_master_thread(), strchr(), strlen(), trx_struct::table_id, TRUE, trx_commit_for_mysql(), trx_start_if_not_started(), ut_a, ut_ad, ut_error, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, ut_print_name(), and ut_print_timestamp().
Referenced by dict_create_or_check_foreign_constraint_tables(), row_create_index_for_mysql(), row_create_table_for_mysql(), row_drop_database_for_mysql(), row_drop_table_for_mysql_in_background(), row_table_add_foreign_constraints(), and trx_rollback_or_clean_all_without_sess().
02958 : error code or DB_SUCCESS */ 02959 const char* name, /* in: table name */ 02960 trx_t* trx, /* in: transaction handle */ 02961 ibool drop_db)/* in: TRUE=dropping whole database */ 02962 { 02963 dict_foreign_t* foreign; 02964 dict_table_t* table; 02965 ulint space_id; 02966 ulint err; 02967 const char* table_name; 02968 ulint namelen; 02969 char* dir_path_of_temp_table = NULL; 02970 ibool success; 02971 ibool locked_dictionary = FALSE; 02972 pars_info_t* info = NULL; 02973 02974 ut_a(name != NULL); 02975 02976 if (srv_created_new_raw) { 02977 fputs( 02978 "InnoDB: A new raw disk partition was initialized or\n" 02979 "InnoDB: innodb_force_recovery is on: we do not allow\n" 02980 "InnoDB: database modifications by the user. Shut down\n" 02981 "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" 02982 "InnoDB: with raw, and innodb_force_... is removed.\n", 02983 stderr); 02984 02985 return(DB_ERROR); 02986 } 02987 02988 trx->op_info = "dropping table"; 02989 02990 trx_start_if_not_started(trx); 02991 02992 /* The table name is prefixed with the database name and a '/'. 02993 Certain table names starting with 'innodb_' have their special 02994 meaning regardless of the database name. Thus, we need to 02995 ignore the database name prefix in the comparisons. */ 02996 table_name = strchr(name, '/'); 02997 ut_a(table_name); 02998 table_name++; 02999 namelen = strlen(table_name) + 1; 03000 03001 if (namelen == sizeof S_innodb_monitor 03002 && !memcmp(table_name, S_innodb_monitor, 03003 sizeof S_innodb_monitor)) { 03004 03005 /* Table name equals "innodb_monitor": 03006 stop monitor prints */ 03007 03008 srv_print_innodb_monitor = FALSE; 03009 srv_print_innodb_lock_monitor = FALSE; 03010 } else if (namelen == sizeof S_innodb_lock_monitor 03011 && !memcmp(table_name, S_innodb_lock_monitor, 03012 sizeof S_innodb_lock_monitor)) { 03013 srv_print_innodb_monitor = FALSE; 03014 srv_print_innodb_lock_monitor = FALSE; 03015 } else if (namelen == sizeof S_innodb_tablespace_monitor 03016 && !memcmp(table_name, S_innodb_tablespace_monitor, 03017 sizeof S_innodb_tablespace_monitor)) { 03018 03019 srv_print_innodb_tablespace_monitor = FALSE; 03020 } else if (namelen == sizeof S_innodb_table_monitor 03021 && !memcmp(table_name, S_innodb_table_monitor, 03022 sizeof S_innodb_table_monitor)) { 03023 03024 srv_print_innodb_table_monitor = FALSE; 03025 } 03026 03027 /* Serialize data dictionary operations with dictionary mutex: 03028 no deadlocks can occur then in these operations */ 03029 03030 if (trx->dict_operation_lock_mode != RW_X_LATCH) { 03031 /* Prevent foreign key checks etc. while we are dropping the 03032 table */ 03033 03034 row_mysql_lock_data_dictionary(trx); 03035 03036 locked_dictionary = TRUE; 03037 } 03038 03039 #ifdef UNIV_SYNC_DEBUG 03040 ut_ad(mutex_own(&(dict_sys->mutex))); 03041 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); 03042 #endif /* UNIV_SYNC_DEBUG */ 03043 03044 table = dict_table_get_low(name); 03045 03046 if (!table) { 03047 err = DB_TABLE_NOT_FOUND; 03048 ut_print_timestamp(stderr); 03049 03050 fputs(" InnoDB: Error: table ", stderr); 03051 ut_print_name(stderr, trx, TRUE, name); 03052 fputs(" does not exist in the InnoDB internal\n" 03053 "InnoDB: data dictionary though MySQL is trying to drop it.\n" 03054 "InnoDB: Have you copied the .frm file of the table to the\n" 03055 "InnoDB: MySQL database directory from another database?\n" 03056 "InnoDB: You can look for further help from\n" 03057 "InnoDB: http://dev.mysql.com/doc/mysql/en/" 03058 "InnoDB_troubleshooting_datadict.html\n", stderr); 03059 goto funct_exit; 03060 } 03061 03062 /* Check if the table is referenced by foreign key constraints from 03063 some other table (not the table itself) */ 03064 03065 foreign = UT_LIST_GET_FIRST(table->referenced_list); 03066 03067 while (foreign && foreign->foreign_table == table) { 03068 check_next_foreign: 03069 foreign = UT_LIST_GET_NEXT(referenced_list, foreign); 03070 } 03071 03072 if (foreign && trx->check_foreigns && 03073 !(drop_db && dict_tables_have_same_db( 03074 name, foreign->foreign_table_name))) { 03075 FILE* ef = dict_foreign_err_file; 03076 03077 /* We only allow dropping a referenced table if 03078 FOREIGN_KEY_CHECKS is set to 0 */ 03079 03080 err = DB_CANNOT_DROP_CONSTRAINT; 03081 03082 mutex_enter(&dict_foreign_err_mutex); 03083 rewind(ef); 03084 ut_print_timestamp(ef); 03085 03086 fputs(" Cannot drop table ", ef); 03087 ut_print_name(ef, trx, TRUE, name); 03088 fputs("\n" 03089 "because it is referenced by ", ef); 03090 ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); 03091 putc('\n', ef); 03092 mutex_exit(&dict_foreign_err_mutex); 03093 03094 goto funct_exit; 03095 } 03096 03097 if (foreign && trx->check_foreigns) { 03098 goto check_next_foreign; 03099 } 03100 03101 if (table->n_mysql_handles_opened > 0) { 03102 ibool added; 03103 03104 added = row_add_table_to_background_drop_list(table); 03105 03106 if (added) { 03107 ut_print_timestamp(stderr); 03108 fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); 03109 ut_print_name(stderr, trx, TRUE, table->name); 03110 fputs("\n" 03111 "InnoDB: though there are still open handles to it.\n" 03112 "InnoDB: Adding the table to the background drop queue.\n", 03113 stderr); 03114 03115 /* We return DB_SUCCESS to MySQL though the drop will 03116 happen lazily later */ 03117 03118 err = DB_SUCCESS; 03119 } else { 03120 /* The table is already in the background drop list */ 03121 err = DB_ERROR; 03122 } 03123 03124 goto funct_exit; 03125 } 03126 03127 /* TODO: could we replace the counter n_foreign_key_checks_running 03128 with lock checks on the table? Acquire here an exclusive lock on the 03129 table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that 03130 they can cope with the table having been dropped here? Foreign key 03131 checks take an IS or IX lock on the table. */ 03132 03133 if (table->n_foreign_key_checks_running > 0) { 03134 03135 ibool added; 03136 03137 added = row_add_table_to_background_drop_list(table); 03138 03139 if (added) { 03140 ut_print_timestamp(stderr); 03141 fputs(" InnoDB: You are trying to drop table ", stderr); 03142 ut_print_name(stderr, trx, TRUE, table->name); 03143 fputs("\n" 03144 "InnoDB: though there is a foreign key check running on it.\n" 03145 "InnoDB: Adding the table to the background drop queue.\n", 03146 stderr); 03147 03148 /* We return DB_SUCCESS to MySQL though the drop will 03149 happen lazily later */ 03150 03151 err = DB_SUCCESS; 03152 } else { 03153 /* The table is already in the background drop list */ 03154 err = DB_ERROR; 03155 } 03156 03157 goto funct_exit; 03158 } 03159 03160 /* Remove any locks there are on the table or its records */ 03161 03162 lock_reset_all_on_table(table); 03163 03164 trx->dict_operation = TRUE; 03165 trx->table_id = table->id; 03166 03167 /* We use the private SQL parser of Innobase to generate the 03168 query graphs needed in deleting the dictionary data from system 03169 tables in Innobase. Deleting a row from SYS_INDEXES table also 03170 frees the file segments of the B-tree associated with the index. */ 03171 03172 info = pars_info_create(); 03173 03174 pars_info_add_str_literal(info, "table_name", name); 03175 03176 err = que_eval_sql(info, 03177 "PROCEDURE DROP_TABLE_PROC () IS\n" 03178 "sys_foreign_id CHAR;\n" 03179 "table_id CHAR;\n" 03180 "index_id CHAR;\n" 03181 "foreign_id CHAR;\n" 03182 "found INT;\n" 03183 "BEGIN\n" 03184 "SELECT ID INTO table_id\n" 03185 "FROM SYS_TABLES\n" 03186 "WHERE NAME = :table_name\n" 03187 "LOCK IN SHARE MODE;\n" 03188 "IF (SQL % NOTFOUND) THEN\n" 03189 " COMMIT WORK;\n" 03190 " RETURN;\n" 03191 "END IF;\n" 03192 "found := 1;\n" 03193 "SELECT ID INTO sys_foreign_id\n" 03194 "FROM SYS_TABLES\n" 03195 "WHERE NAME = 'SYS_FOREIGN'\n" 03196 "LOCK IN SHARE MODE;\n" 03197 "IF (SQL % NOTFOUND) THEN\n" 03198 " found := 0;\n" 03199 "END IF;\n" 03200 "IF (:table_name = 'SYS_FOREIGN') THEN\n" 03201 " found := 0;\n" 03202 "END IF;\n" 03203 "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n" 03204 " found := 0;\n" 03205 "END IF;\n" 03206 "WHILE found = 1 LOOP\n" 03207 " SELECT ID INTO foreign_id\n" 03208 " FROM SYS_FOREIGN\n" 03209 " WHERE FOR_NAME = :table_name\n" 03210 " AND TO_BINARY(FOR_NAME) = TO_BINARY(:table_name)\n" 03211 " LOCK IN SHARE MODE;\n" 03212 " IF (SQL % NOTFOUND) THEN\n" 03213 " found := 0;\n" 03214 " ELSE" 03215 " DELETE FROM SYS_FOREIGN_COLS WHERE ID = foreign_id;\n" 03216 " DELETE FROM SYS_FOREIGN WHERE ID = foreign_id;\n" 03217 " END IF;\n" 03218 "END LOOP;\n" 03219 "found := 1;\n" 03220 "WHILE found = 1 LOOP\n" 03221 " SELECT ID INTO index_id\n" 03222 " FROM SYS_INDEXES\n" 03223 " WHERE TABLE_ID = table_id\n" 03224 " LOCK IN SHARE MODE;\n" 03225 " IF (SQL % NOTFOUND) THEN\n" 03226 " found := 0;\n" 03227 " ELSE" 03228 " DELETE FROM SYS_FIELDS WHERE INDEX_ID = index_id;\n" 03229 " DELETE FROM SYS_INDEXES WHERE ID = index_id\n" 03230 " AND TABLE_ID = table_id;\n" 03231 " END IF;\n" 03232 "END LOOP;\n" 03233 "DELETE FROM SYS_COLUMNS WHERE TABLE_ID = table_id;\n" 03234 "DELETE FROM SYS_TABLES WHERE ID = table_id;\n" 03235 "COMMIT WORK;\n" 03236 "END;\n" 03237 , FALSE, trx); 03238 03239 if (err != DB_SUCCESS) { 03240 ut_a(err == DB_OUT_OF_FILE_SPACE); 03241 03242 err = DB_MUST_GET_MORE_FILE_SPACE; 03243 03244 row_mysql_handle_errors(&err, trx, NULL, NULL); 03245 03246 ut_error; 03247 } else { 03248 ibool is_path; 03249 const char* name_or_path; 03250 03251 space_id = table->space; 03252 03253 if (table->dir_path_of_temp_table != NULL) { 03254 dir_path_of_temp_table = 03255 mem_strdup(table->dir_path_of_temp_table); 03256 is_path = TRUE; 03257 name_or_path = dir_path_of_temp_table; 03258 } else { 03259 is_path = FALSE; 03260 name_or_path = name; 03261 } 03262 03263 dict_table_remove_from_cache(table); 03264 03265 if (dict_load_table(name) != NULL) { 03266 ut_print_timestamp(stderr); 03267 fputs(" InnoDB: Error: not able to remove table ", 03268 stderr); 03269 ut_print_name(stderr, trx, TRUE, name); 03270 fputs(" from the dictionary cache!\n", stderr); 03271 err = DB_ERROR; 03272 } 03273 03274 /* Do not drop possible .ibd tablespace if something went 03275 wrong: we do not want to delete valuable data of the user */ 03276 03277 if (err == DB_SUCCESS && space_id > 0) { 03278 if (!fil_space_for_table_exists_in_mem(space_id, 03279 name_or_path, 03280 is_path, 03281 FALSE, TRUE)) { 03282 err = DB_SUCCESS; 03283 03284 fprintf(stderr, 03285 "InnoDB: We removed now the InnoDB internal data dictionary entry\n" 03286 "InnoDB: of table "); 03287 ut_print_name(stderr, trx, TRUE, name); 03288 fprintf(stderr, ".\n"); 03289 03290 goto funct_exit; 03291 } 03292 03293 success = fil_delete_tablespace(space_id); 03294 03295 if (!success) { 03296 fprintf(stderr, 03297 "InnoDB: We removed now the InnoDB internal data dictionary entry\n" 03298 "InnoDB: of table "); 03299 ut_print_name(stderr, trx, TRUE, name); 03300 fprintf(stderr, ".\n"); 03301 03302 ut_print_timestamp(stderr); 03303 fprintf(stderr, 03304 " InnoDB: Error: not able to delete tablespace %lu of table ", 03305 (ulong) space_id); 03306 ut_print_name(stderr, trx, TRUE, name); 03307 fputs("!\n", stderr); 03308 err = DB_ERROR; 03309 } 03310 } 03311 } 03312 funct_exit: 03313 03314 trx_commit_for_mysql(trx); 03315 03316 if (locked_dictionary) { 03317 row_mysql_unlock_data_dictionary(trx); 03318 } 03319 03320 if (dir_path_of_temp_table) { 03321 mem_free(dir_path_of_temp_table); 03322 } 03323 03324 trx->op_info = ""; 03325 03326 #ifndef UNIV_HOTBACKUP 03327 srv_wake_master_thread(); 03328 #endif /* !UNIV_HOTBACKUP */ 03329 03330 return((int) err); 03331 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint row_drop_tables_for_mysql_in_background | ( | void | ) |
Definition at line 2227 of file row0mysql.c.
References DB_SUCCESS, dict_sys, dict_table_get_low(), kernel_mutex, mem_free, dict_sys_struct::mutex, mutex_enter, mutex_exit(), NULL, row_drop_table_for_mysql_in_background(), row_mysql_drop_struct::table_name, TRUE, UT_LIST_GET_FIRST, UT_LIST_GET_LEN, UT_LIST_INIT, UT_LIST_REMOVE, and ut_print_timestamp().
Referenced by srv_master_thread().
02229 : how many tables dropped 02230 + remaining tables in list */ 02231 { 02232 row_mysql_drop_t* drop; 02233 dict_table_t* table; 02234 ulint n_tables; 02235 ulint n_tables_dropped = 0; 02236 loop: 02237 mutex_enter(&kernel_mutex); 02238 02239 if (!row_mysql_drop_list_inited) { 02240 02241 UT_LIST_INIT(row_mysql_drop_list); 02242 row_mysql_drop_list_inited = TRUE; 02243 } 02244 02245 drop = UT_LIST_GET_FIRST(row_mysql_drop_list); 02246 02247 n_tables = UT_LIST_GET_LEN(row_mysql_drop_list); 02248 02249 mutex_exit(&kernel_mutex); 02250 02251 if (drop == NULL) { 02252 /* All tables dropped */ 02253 02254 return(n_tables + n_tables_dropped); 02255 } 02256 02257 mutex_enter(&(dict_sys->mutex)); 02258 table = dict_table_get_low(drop->table_name); 02259 mutex_exit(&(dict_sys->mutex)); 02260 02261 if (table == NULL) { 02262 /* If for some reason the table has already been dropped 02263 through some other mechanism, do not try to drop it */ 02264 02265 goto already_dropped; 02266 } 02267 02268 if (DB_SUCCESS != row_drop_table_for_mysql_in_background( 02269 drop->table_name)) { 02270 /* If the DROP fails for some table, we return, and let the 02271 main thread retry later */ 02272 02273 return(n_tables + n_tables_dropped); 02274 } 02275 02276 n_tables_dropped++; 02277 02278 already_dropped: 02279 mutex_enter(&kernel_mutex); 02280 02281 UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop); 02282 02283 ut_print_timestamp(stderr); 02284 fprintf(stderr, 02285 " InnoDB: Dropped table %s in background drop queue.\n", 02286 drop->table_name); 02287 02288 mem_free(drop->table_name); 02289 02290 mem_free(drop); 02291 02292 mutex_exit(&kernel_mutex); 02293 02294 goto loop; 02295 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint row_get_background_drop_list_len_low | ( | void | ) |
Definition at line 2302 of file row0mysql.c.
References kernel_mutex, TRUE, ut_ad, UT_LIST_GET_LEN, and UT_LIST_INIT.
Referenced by srv_master_thread().
02304 : how many tables in list */ 02305 { 02306 #ifdef UNIV_SYNC_DEBUG 02307 ut_ad(mutex_own(&kernel_mutex)); 02308 #endif /* UNIV_SYNC_DEBUG */ 02309 02310 if (!row_mysql_drop_list_inited) { 02311 02312 UT_LIST_INIT(row_mysql_drop_list); 02313 row_mysql_drop_list_inited = TRUE; 02314 } 02315 02316 return(UT_LIST_GET_LEN(row_mysql_drop_list)); 02317 }
Here is the caller graph for this function:

| ulint row_get_mysql_key_number_for_index | ( | dict_index_t * | index | ) |
Definition at line 1637 of file row0mysql.c.
References dict_table_get_first_index(), dict_table_get_next_index(), index(), row_table_got_default_clust_index(), and ut_a.
01640 { 01641 dict_index_t* ind; 01642 ulint i; 01643 01644 ut_a(index); 01645 01646 i = 0; 01647 ind = dict_table_get_first_index(index->table); 01648 01649 while (index != ind) { 01650 ind = dict_table_get_next_index(ind); 01651 i++; 01652 } 01653 01654 if (row_table_got_default_clust_index(index->table)) { 01655 ut_a(i > 0); 01656 i--; 01657 } 01658 01659 return(i); 01660 }
Here is the call graph for this function:

| upd_t* row_get_prebuilt_update_vector | ( | row_prebuilt_t * | prebuilt | ) |
Definition at line 1257 of file row0mysql.c.
References row_prebuilt_struct::heap, NULL, pars_complete_graph_for_exec(), QUE_FORK_ACTIVE, que_node_get_parent(), row_create_update_node_for_mysql(), que_fork_struct::state, row_prebuilt_struct::table, row_prebuilt_struct::trx, row_prebuilt_struct::upd_graph, row_prebuilt_struct::upd_node, upd_node_struct::update, and ut_ad.
01259 : prebuilt update vector */ 01260 row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL 01261 handle */ 01262 { 01263 dict_table_t* table = prebuilt->table; 01264 upd_node_t* node; 01265 01266 ut_ad(prebuilt && table && prebuilt->trx); 01267 01268 if (prebuilt->upd_node == NULL) { 01269 01270 /* Not called before for this handle: create an update node 01271 and query graph to the prebuilt struct */ 01272 01273 node = row_create_update_node_for_mysql(table, prebuilt->heap); 01274 01275 prebuilt->upd_node = node; 01276 01277 prebuilt->upd_graph = 01278 que_node_get_parent( 01279 pars_complete_graph_for_exec(node, 01280 prebuilt->trx, 01281 prebuilt->heap)); 01282 prebuilt->upd_graph->state = QUE_FORK_ACTIVE; 01283 } 01284 01285 return(prebuilt->upd_node->update); 01286 }
Here is the call graph for this function:

| int row_import_tablespace_for_mysql | ( | const char * | name, | |
| trx_t * | trx | |||
| ) |
Definition at line 2560 of file row0mysql.c.
References DB_ERROR, DB_SUCCESS, DB_TABLE_NOT_FOUND, dict_table_get_low(), err, FALSE, fil_open_single_table_tablespace(), fil_reset_too_high_lsns(), dict_table_struct::ibd_file_missing, ibuf_delete_for_discarded_space(), log_get_lsn(), trx_struct::mysql_thread_id, dict_table_struct::name, trx_struct::op_info, os_thread_get_curr_id(), row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary(), dict_table_struct::space, dict_table_struct::tablespace_discarded, TRUE, trx_commit_for_mysql(), trx_start_if_not_started(), ut_ad, ut_print_name(), and ut_print_timestamp().
02562 : error code or DB_SUCCESS */ 02563 const char* name, /* in: table name */ 02564 trx_t* trx) /* in: transaction handle */ 02565 { 02566 dict_table_t* table; 02567 ibool success; 02568 dulint current_lsn; 02569 ulint err = DB_SUCCESS; 02570 02571 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 02572 02573 trx_start_if_not_started(trx); 02574 02575 trx->op_info = "importing tablespace"; 02576 02577 current_lsn = log_get_lsn(); 02578 02579 /* It is possible, though very improbable, that the lsn's in the 02580 tablespace to be imported have risen above the current system lsn, if 02581 a lengthy purge, ibuf merge, or rollback was performed on a backup 02582 taken with ibbackup. If that is the case, reset page lsn's in the 02583 file. We assume that mysqld was shut down after it performed these 02584 cleanup operations on the .ibd file, so that it stamped the latest lsn 02585 to the FIL_PAGE_FILE_FLUSH_LSN in the first page of the .ibd file. 02586 02587 TODO: reset also the trx id's in clustered index records and write 02588 a new space id to each data page. That would allow us to import clean 02589 .ibd files from another MySQL installation. */ 02590 02591 success = fil_reset_too_high_lsns(name, current_lsn); 02592 02593 if (!success) { 02594 ut_print_timestamp(stderr); 02595 fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr); 02596 ut_print_name(stderr, trx, TRUE, name); 02597 fputs("\n" 02598 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr); 02599 02600 err = DB_ERROR; 02601 02602 row_mysql_lock_data_dictionary(trx); 02603 02604 goto funct_exit; 02605 } 02606 02607 /* Serialize data dictionary operations with dictionary mutex: 02608 no deadlocks can occur then in these operations */ 02609 02610 row_mysql_lock_data_dictionary(trx); 02611 02612 table = dict_table_get_low(name); 02613 02614 if (!table) { 02615 ut_print_timestamp(stderr); 02616 fputs(" InnoDB: table ", stderr); 02617 ut_print_name(stderr, trx, TRUE, name); 02618 fputs("\n" 02619 "InnoDB: does not exist in the InnoDB data dictionary\n" 02620 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", 02621 stderr); 02622 02623 err = DB_TABLE_NOT_FOUND; 02624 02625 goto funct_exit; 02626 } 02627 02628 if (table->space == 0) { 02629 ut_print_timestamp(stderr); 02630 fputs(" InnoDB: Error: table ", stderr); 02631 ut_print_name(stderr, trx, TRUE, name); 02632 fputs("\n" 02633 "InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr); 02634 err = DB_ERROR; 02635 02636 goto funct_exit; 02637 } 02638 02639 if (!table->tablespace_discarded) { 02640 ut_print_timestamp(stderr); 02641 fputs( 02642 " InnoDB: Error: you are trying to IMPORT a tablespace\n" 02643 "InnoDB: ", stderr); 02644 ut_print_name(stderr, trx, TRUE, name); 02645 fputs(", though you have not called DISCARD on it yet\n" 02646 "InnoDB: during the lifetime of the mysqld process!\n", stderr); 02647 02648 err = DB_ERROR; 02649 02650 goto funct_exit; 02651 } 02652 02653 /* Play safe and remove all insert buffer entries, though we should 02654 have removed them already when DISCARD TABLESPACE was called */ 02655 02656 ibuf_delete_for_discarded_space(table->space); 02657 02658 success = fil_open_single_table_tablespace(TRUE, table->space, 02659 table->name); 02660 if (success) { 02661 table->ibd_file_missing = FALSE; 02662 table->tablespace_discarded = FALSE; 02663 } else { 02664 if (table->ibd_file_missing) { 02665 ut_print_timestamp(stderr); 02666 fputs( 02667 " InnoDB: cannot find or open in the database directory the .ibd file of\n" 02668 "InnoDB: table ", stderr); 02669 ut_print_name(stderr, trx, TRUE, name); 02670 fputs("\n" 02671 "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", 02672 stderr); 02673 } 02674 02675 err = DB_ERROR; 02676 } 02677 02678 funct_exit: 02679 trx_commit_for_mysql(trx); 02680 02681 row_mysql_unlock_data_dictionary(trx); 02682 02683 trx->op_info = ""; 02684 02685 return((int) err); 02686 }
Here is the call graph for this function:

| int row_insert_for_mysql | ( | byte * | mysql_rec, | |
| row_prebuilt_t * | prebuilt | |||
| ) |
Definition at line 1061 of file row0mysql.c.
References DB_ERROR, DB_SUCCESS, err, trx_struct::error_state, FALSE, dict_table_struct::ibd_file_missing, row_prebuilt_struct::ins_graph, row_prebuilt_struct::ins_node, INS_NODE_ALLOC_ROW_ID, INS_NODE_SET_IX_LOCK, row_prebuilt_struct::magic_n, mem_analyze_corruption(), trx_struct::mysql_thread_id, dict_table_struct::name, NULL, trx_struct::op_info, os_thread_get_curr_id(), que_thr_struct::prev_node, que_fork_get_first_thr(), QUE_THR_LOCK_NOLOCK, QUE_THR_LOCK_ROW, que_thr_move_to_run_state_for_mysql(), que_thr_stop_for_mysql(), que_thr_stop_for_mysql_no_error(), ins_node_struct::row, row_get_prebuilt_insert_row(), row_ins_step(), row_mysql_convert_row_to_innobase(), row_mysql_delay_if_needed(), row_mysql_handle_errors(), ROW_PREBUILT_ALLOCATED, row_update_statistics_if_needed(), que_thr_struct::run_node, row_prebuilt_struct::sql_stat_start, srv_created_new_raw, srv_force_recovery, srv_n_rows_inserted, dict_table_struct::stat_n_rows, ins_node_struct::state, row_prebuilt_struct::table, TRUE, row_prebuilt_struct::trx, trx_savept_take(), trx_start_if_not_started(), ut_ad, ut_error, ut_print_name(), and ut_print_timestamp().
01063 : error code or DB_SUCCESS */ 01064 byte* mysql_rec, /* in: row in the MySQL format */ 01065 row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL 01066 handle */ 01067 { 01068 trx_savept_t savept; 01069 que_thr_t* thr; 01070 ulint err; 01071 ibool was_lock_wait; 01072 trx_t* trx = prebuilt->trx; 01073 ins_node_t* node = prebuilt->ins_node; 01074 01075 ut_ad(trx); 01076 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 01077 01078 if (prebuilt->table->ibd_file_missing) { 01079 ut_print_timestamp(stderr); 01080 fprintf(stderr, " InnoDB: Error:\n" 01081 "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" 01082 "InnoDB: table %s does not exist.\n" 01083 "InnoDB: Have you deleted the .ibd file from the database directory under\n" 01084 "InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n" 01085 "InnoDB: Look from\n" 01086 "http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n" 01087 "InnoDB: how you can resolve the problem.\n", 01088 prebuilt->table->name); 01089 return(DB_ERROR); 01090 } 01091 01092 if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { 01093 fprintf(stderr, 01094 "InnoDB: Error: trying to free a corrupt\n" 01095 "InnoDB: table handle. Magic n %lu, table name", 01096 (ulong) prebuilt->magic_n); 01097 ut_print_name(stderr, prebuilt->trx, TRUE, 01098 prebuilt->table->name); 01099 putc('\n', stderr); 01100 01101 mem_analyze_corruption(prebuilt); 01102 01103 ut_error; 01104 } 01105 01106 if (srv_created_new_raw || srv_force_recovery) { 01107 fputs( 01108 "InnoDB: A new raw disk partition was initialized or\n" 01109 "InnoDB: innodb_force_recovery is on: we do not allow\n" 01110 "InnoDB: database modifications by the user. Shut down\n" 01111 "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" 01112 "InnoDB: with raw, and innodb_force_... is removed.\n", 01113 stderr); 01114 01115 return(DB_ERROR); 01116 } 01117 01118 trx->op_info = "inserting"; 01119 01120 row_mysql_delay_if_needed(); 01121 01122 trx_start_if_not_started(trx); 01123 01124 if (node == NULL) { 01125 row_get_prebuilt_insert_row(prebuilt); 01126 node = prebuilt->ins_node; 01127 } 01128 01129 row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec); 01130 01131 savept = trx_savept_take(trx); 01132 01133 thr = que_fork_get_first_thr(prebuilt->ins_graph); 01134 01135 if (prebuilt->sql_stat_start) { 01136 node->state = INS_NODE_SET_IX_LOCK; 01137 prebuilt->sql_stat_start = FALSE; 01138 } else { 01139 node->state = INS_NODE_ALLOC_ROW_ID; 01140 } 01141 01142 que_thr_move_to_run_state_for_mysql(thr, trx); 01143 01144 run_again: 01145 thr->run_node = node; 01146 thr->prev_node = node; 01147 01148 row_ins_step(thr); 01149 01150 err = trx->error_state; 01151 01152 if (err != DB_SUCCESS) { 01153 que_thr_stop_for_mysql(thr); 01154 01155 /* TODO: what is this? */ thr->lock_state= QUE_THR_LOCK_ROW; 01156 01157 was_lock_wait = row_mysql_handle_errors(&err, trx, thr, 01158 &savept); 01159 thr->lock_state= QUE_THR_LOCK_NOLOCK; 01160 01161 if (was_lock_wait) { 01162 goto run_again; 01163 } 01164 01165 trx->op_info = ""; 01166 01167 return((int) err); 01168 } 01169 01170 que_thr_stop_for_mysql_no_error(thr, trx); 01171 01172 prebuilt->table->stat_n_rows++; 01173 01174 srv_n_rows_inserted++; 01175 01176 if (prebuilt->table->stat_n_rows == 0) { 01177 /* Avoid wrap-over */ 01178 prebuilt->table->stat_n_rows--; 01179 } 01180 01181 row_update_statistics_if_needed(prebuilt->table); 01182 trx->op_info = ""; 01183 01184 return((int) err); 01185 }
Here is the call graph for this function:

| int row_lock_table_autoinc_for_mysql | ( | row_prebuilt_t * | prebuilt | ) |
Definition at line 912 of file row0mysql.c.
References trx_struct::auto_inc_lock, DB_SUCCESS, err, trx_struct::error_state, row_prebuilt_struct::ins_graph, row_prebuilt_struct::ins_node, LOCK_AUTO_INC, lock_table(), trx_struct::mysql_thread_id, NULL, trx_struct::op_info, os_thread_get_curr_id(), que_thr_struct::prev_node, que_fork_get_first_thr(), que_thr_move_to_run_state_for_mysql(), que_thr_stop_for_mysql(), que_thr_stop_for_mysql_no_error(), row_get_prebuilt_insert_row(), row_mysql_handle_errors(), que_thr_struct::run_node, row_prebuilt_struct::table, row_prebuilt_struct::trx, trx_start_if_not_started(), and ut_ad.
00914 : error code or DB_SUCCESS */ 00915 row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL 00916 table handle */ 00917 { 00918 trx_t* trx = prebuilt->trx; 00919 ins_node_t* node = prebuilt->ins_node; 00920 que_thr_t* thr; 00921 ulint err; 00922 ibool was_lock_wait; 00923 00924 ut_ad(trx); 00925 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 00926 00927 if (trx->auto_inc_lock) { 00928 00929 return(DB_SUCCESS); 00930 } 00931 00932 trx->op_info = "setting auto-inc lock"; 00933 00934 if (node == NULL) { 00935 row_get_prebuilt_insert_row(prebuilt); 00936 node = prebuilt->ins_node; 00937 } 00938 00939 /* We use the insert query graph as the dummy graph needed 00940 in the lock module call */ 00941 00942 thr = que_fork_get_first_thr(prebuilt->ins_graph); 00943 00944 que_thr_move_to_run_state_for_mysql(thr, trx); 00945 00946 run_again: 00947 thr->run_node = node; 00948 thr->prev_node = node; 00949 00950 /* It may be that the current session has not yet started 00951 its transaction, or it has been committed: */ 00952 00953 trx_start_if_not_started(trx); 00954 00955 err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); 00956 00957 trx->error_state = err; 00958 00959 if (err != DB_SUCCESS) { 00960 que_thr_stop_for_mysql(thr); 00961 00962 was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); 00963 00964 if (was_lock_wait) { 00965 goto run_again; 00966 } 00967 00968 trx->op_info = ""; 00969 00970 return((int) err); 00971 } 00972 00973 que_thr_stop_for_mysql_no_error(thr, trx); 00974 00975 trx->op_info = ""; 00976 00977 return((int) err); 00978 }
Here is the call graph for this function:

| int row_lock_table_for_mysql | ( | row_prebuilt_t * | prebuilt, | |
| dict_table_t * | table, | |||
| ulint | mode | |||
| ) |
Definition at line 984 of file row0mysql.c.
References que_thr_struct::common, DB_SUCCESS, err, trx_struct::error_state, lock_table(), trx_struct::mysql_thread_id, NULL, trx_struct::op_info, os_thread_get_curr_id(), que_common_struct::parent, que_thr_struct::prev_node, que_fork_get_first_thr(), que_thr_move_to_run_state_for_mysql(), que_thr_stop_for_mysql(), que_thr_stop_for_mysql_no_error(), row_mysql_handle_errors(), row_prebuild_sel_graph(), que_thr_struct::run_node, row_prebuilt_struct::sel_graph, row_prebuilt_struct::select_lock_type, row_prebuilt_struct::table, row_prebuilt_struct::trx, trx_start_if_not_started(), and ut_ad.
00986 : error code or DB_SUCCESS */ 00987 row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL 00988 table handle */ 00989 dict_table_t* table, /* in: table to lock, or NULL 00990 if prebuilt->table should be 00991 locked as 00992 prebuilt->select_lock_type */ 00993 ulint mode) /* in: lock mode of table 00994 (ignored if table==NULL) */ 00995 { 00996 trx_t* trx = prebuilt->trx; 00997 que_thr_t* thr; 00998 ulint err; 00999 ibool was_lock_wait; 01000 01001 ut_ad(trx); 01002 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 01003 01004 trx->op_info = "setting table lock"; 01005 01006 if (prebuilt->sel_graph == NULL) { 01007 /* Build a dummy select query graph */ 01008 row_prebuild_sel_graph(prebuilt); 01009 } 01010 01011 /* We use the select query graph as the dummy graph needed 01012 in the lock module call */ 01013 01014 thr = que_fork_get_first_thr(prebuilt->sel_graph); 01015 01016 que_thr_move_to_run_state_for_mysql(thr, trx); 01017 01018 run_again: 01019 thr->run_node = thr; 01020 thr->prev_node = thr->common.parent; 01021 01022 /* It may be that the current session has not yet started 01023 its transaction, or it has been committed: */ 01024 01025 trx_start_if_not_started(trx); 01026 01027 if (table) { 01028 err = lock_table(0, table, mode, thr); 01029 } else { 01030 err = lock_table(0, prebuilt->table, 01031 prebuilt->select_lock_type, thr); 01032 } 01033 01034 trx->error_state = err; 01035 01036 if (err != DB_SUCCESS) { 01037 que_thr_stop_for_mysql(thr); 01038 01039 was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); 01040 01041 if (was_lock_wait) { 01042 goto run_again; 01043 } 01044 01045 trx->op_info = ""; 01046 01047 return((int) err); 01048 } 01049 01050 que_thr_stop_for_mysql_no_error(thr, trx); 01051 01052 trx->op_info = ""; 01053 01054 return((int) err); 01055 }
Here is the call graph for this function:

| void row_mysql_freeze_data_dictionary | ( | trx_t * | trx | ) |
Definition at line 1709 of file row0mysql.c.
References dict_operation_lock, trx_struct::dict_operation_lock_mode, rw_lock_s_lock, RW_S_LATCH, and ut_a.
Referenced by row_ins_check_foreign_constraints(), row_purge_parse_undo_rec(), row_undo(), row_upd_check_references_constraints(), row_upd_index_is_referenced(), and srv_suspend_mysql_thread().
01711 : transaction */ 01712 { 01713 ut_a(trx->dict_operation_lock_mode == 0); 01714 01715 rw_lock_s_lock(&dict_operation_lock); 01716 01717 trx->dict_operation_lock_mode = RW_S_LATCH; 01718 }
Here is the caller graph for this function:

| ibool row_mysql_handle_errors | ( | ulint * | new_err, | |
| trx_t * | trx, | |||
| que_thr_t * | thr, | |||
| trx_savept_t * | savept | |||
| ) |
Definition at line 457 of file row0mysql.c.
References DB_CANNOT_ADD_CONSTRAINT, DB_CORRUPTION, DB_DEADLOCK, DB_DUPLICATE_KEY, DB_FOREIGN_DUPLICATE_KEY, DB_LOCK_TABLE_FULL, DB_LOCK_WAIT, DB_LOCK_WAIT_TIMEOUT, DB_MUST_GET_MORE_FILE_SPACE, DB_NO_REFERENCED_ROW, DB_OUT_OF_FILE_SPACE, DB_ROW_IS_REFERENCED, DB_SUCCESS, DB_TOO_BIG_RECORD, err, trx_struct::error_state, exit, FALSE, NULL, que_thr_stop_for_mysql(), srv_suspend_mysql_thread(), TRUE, trx_general_rollback_for_mysql(), ut_a, and ut_error.
Referenced by row_drop_table_for_mysql(), row_insert_for_mysql(), row_lock_table_autoinc_for_mysql(), row_lock_table_for_mysql(), row_search_for_mysql(), and row_update_for_mysql().
00459 : TRUE if it was a lock wait and 00460 we should continue running the query thread */ 00461 ulint* new_err,/* out: possible new error encountered in 00462 lock wait, or if no new error, the value 00463 of trx->error_state at the entry of this 00464 function */ 00465 trx_t* trx, /* in: transaction */ 00466 que_thr_t* thr, /* in: query thread */ 00467 trx_savept_t* savept) /* in: savepoint or NULL */ 00468 { 00469 #ifndef UNIV_HOTBACKUP 00470 ulint err; 00471 00472 handle_new_error: 00473 err = trx->error_state; 00474 00475 ut_a(err != DB_SUCCESS); 00476 00477 trx->error_state = DB_SUCCESS; 00478 00479 if ((err == DB_DUPLICATE_KEY) 00480 || (err == DB_FOREIGN_DUPLICATE_KEY)) { 00481 if (savept) { 00482 /* Roll back the latest, possibly incomplete 00483 insertion or update */ 00484 00485 trx_general_rollback_for_mysql(trx, TRUE, savept); 00486 } 00487 } else if (err == DB_TOO_BIG_RECORD) { 00488 if (savept) { 00489 /* Roll back the latest, possibly incomplete 00490 insertion or update */ 00491 00492 trx_general_rollback_for_mysql(trx, TRUE, savept); 00493 } 00494 /* MySQL will roll back the latest SQL statement */ 00495 } else if (err == DB_ROW_IS_REFERENCED 00496 || err == DB_NO_REFERENCED_ROW 00497 || err == DB_CANNOT_ADD_CONSTRAINT) { 00498 if (savept) { 00499 /* Roll back the latest, possibly incomplete 00500 insertion or update */ 00501 00502 trx_general_rollback_for_mysql(trx, TRUE, savept); 00503 } 00504 /* MySQL will roll back the latest SQL statement */ 00505 } else if (err == DB_LOCK_WAIT) { 00506 00507 srv_suspend_mysql_thread(thr); 00508 00509 if (trx->error_state != DB_SUCCESS) { 00510 que_thr_stop_for_mysql(thr); 00511 00512 goto handle_new_error; 00513 } 00514 00515 *new_err = err; 00516 00517 return(TRUE); 00518 00519 } else if (err == DB_DEADLOCK 00520 || err == DB_LOCK_TABLE_FULL) { 00521 /* Roll back the whole transaction; this resolution was added 00522 to version 3.23.43 */ 00523 00524 trx_general_rollback_for_mysql(trx, FALSE, NULL); 00525 00526 } else if (err == DB_OUT_OF_FILE_SPACE 00527 || err == DB_LOCK_WAIT_TIMEOUT) { 00528 if (savept) { 00529 /* Roll back the latest, possibly incomplete 00530 insertion or update */ 00531 00532 trx_general_rollback_for_mysql(trx, TRUE, savept); 00533 } 00534 /* MySQL will roll back the latest SQL statement */ 00535 00536 } else if (err == DB_MUST_GET_MORE_FILE_SPACE) { 00537 00538 fputs( 00539 "InnoDB: The database cannot continue operation because of\n" 00540 "InnoDB: lack of space. You must add a new data file to\n" 00541 "InnoDB: my.cnf and restart the database.\n", stderr); 00542 00543 exit(1); 00544 } else if (err == DB_CORRUPTION) { 00545 00546 fputs( 00547 "InnoDB: We detected index corruption in an InnoDB type table.\n" 00548 "InnoDB: You have to dump + drop + reimport the table or, in\n" 00549 "InnoDB: a case of widespread corruption, dump all InnoDB\n" 00550 "InnoDB: tables and recreate the whole InnoDB tablespace.\n" 00551 "InnoDB: If the mysqld server crashes after the startup or when\n" 00552 "InnoDB: you dump the tables, look at\n" 00553 "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html" 00554 " for help.\n", stderr); 00555 00556 } else { 00557 fprintf(stderr, "InnoDB: unknown error code %lu\n", 00558 (ulong) err); 00559 ut_error; 00560 } 00561 00562 if (trx->error_state != DB_SUCCESS) { 00563 *new_err = trx->error_state; 00564 } else { 00565 *new_err = err; 00566 } 00567 00568 trx->error_state = DB_SUCCESS; 00569 00570 return(FALSE); 00571 #else /* UNIV_HOTBACKUP */ 00572 /* This function depends on MySQL code that is not included in 00573 InnoDB Hot Backup builds. Besides, this function should never 00574 be called in InnoDB Hot Backup. */ 00575 ut_error; 00576 return(FALSE); 00577 #endif /* UNIV_HOTBACKUP */ 00578 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_mysql_lock_data_dictionary | ( | trx_t * | trx | ) |
Definition at line 1740 of file row0mysql.c.
References dict_operation_lock, trx_struct::dict_operation_lock_mode, dict_sys, dict_sys_struct::mutex, mutex_enter, rw_lock_x_lock, RW_X_LATCH, and ut_a.
Referenced by dict_create_or_check_foreign_constraint_tables(), row_discard_tablespace_for_mysql(), row_drop_database_for_mysql(), row_drop_table_for_mysql(), row_import_tablespace_for_mysql(), row_rename_table_for_mysql(), row_truncate_table_for_mysql(), and trx_rollback_or_clean_all_without_sess().
01742 : transaction */ 01743 { 01744 ut_a(trx->dict_operation_lock_mode == 0 01745 || trx->dict_operation_lock_mode == RW_X_LATCH); 01746 01747 /* Serialize data dictionary operations with dictionary mutex: 01748 no deadlocks or lock waits can occur then in these operations */ 01749 01750 rw_lock_x_lock(&dict_operation_lock); 01751 trx->dict_operation_lock_mode = RW_X_LATCH; 01752 01753 mutex_enter(&(dict_sys->mutex)); 01754 }
Here is the caller graph for this function:

| void row_mysql_prebuilt_free_blob_heap | ( | row_prebuilt_t * | prebuilt | ) |
Definition at line 114 of file row0mysql.c.
References row_prebuilt_struct::blob_heap, mem_heap_free, and NULL.
00116 : prebuilt struct of a 00117 ha_innobase:: table handle */ 00118 { 00119 mem_heap_free(prebuilt->blob_heap); 00120 prebuilt->blob_heap = NULL; 00121 }
Definition at line 219 of file row0mysql.c.
References data, mach_read_from_n_little_endian(), and ut_memcpy().
00221 : pointer to BLOB data */ 00222 ulint* len, /* out: BLOB length */ 00223 byte* ref, /* in: BLOB reference in the MySQL format */ 00224 ulint col_len) /* in: BLOB reference length (not BLOB 00225 length) */ 00226 { 00227 byte* data; 00228 00229 *len = mach_read_from_n_little_endian(ref, col_len - 8); 00230 00231 ut_memcpy(&data, ref + col_len - 8, sizeof(byte*)); 00232 00233 return(data); 00234 }
Here is the call graph for this function:

Definition at line 157 of file row0mysql.c.
References mach_read_from_1(), mach_read_from_2_little_endian(), and ut_a.
00159 : pointer to the data, we skip the 1 or 2 bytes 00160 at the start that are used to store the len */ 00161 ulint* len, /* out: variable-length field length */ 00162 byte* field, /* in: field in the MySQL format */ 00163 ulint lenlen) /* in: storage length of len: either 1 or 2 bytes */ 00164 { 00165 if (lenlen == 2) { 00166 *len = mach_read_from_2_little_endian(field); 00167 00168 return(field + 2); 00169 } 00170 00171 ut_a(lenlen == 1); 00172 00173 *len = mach_read_from_1(field); 00174 00175 return(field + 1); 00176 }
Here is the call graph for this function:

Definition at line 182 of file row0mysql.c.
References mach_write_to_n_little_endian(), memset, ut_a, and ut_memcpy().
00184 : where to store */ 00185 ulint col_len, /* in: dest buffer size: determines into 00186 how many bytes the BLOB length is stored, 00187 the space for the length may vary from 1 00188 to 4 bytes */ 00189 byte* data, /* in: BLOB data; if the value to store 00190 is SQL NULL this should be NULL pointer */ 00191 ulint len) /* in: BLOB length; if the value to store 00192 is SQL NULL this should be 0; remember 00193 also to set the NULL bit in the MySQL record 00194 header! */ 00195 { 00196 /* MySQL might assume the field is set to zero except the length and 00197 the pointer fields */ 00198 00199 memset(dest, '\0', col_len); 00200 00201 /* In dest there are 1 - 4 bytes reserved for the BLOB length, 00202 and after that 8 bytes reserved for the pointer to the data. 00203 In 32-bit architectures we only use the first 4 bytes of the pointer 00204 slot. */ 00205 00206 ut_a(col_len - 8 > 1 || len < 256); 00207 ut_a(col_len - 8 > 2 || len < 256 * 256); 00208 ut_a(col_len - 8 > 3 || len < 256 * 256 * 256); 00209 00210 mach_write_to_n_little_endian(dest, col_len - 8, len); 00211 00212 ut_memcpy(dest + col_len - 8, &data, sizeof(byte*)); 00213 }
Here is the call graph for this function:

| byte* row_mysql_store_col_in_innobase_format | ( | dfield_t * | dfield, | |
| byte * | buf, | |||
| ibool | row_format_col, | |||
| byte * | mysql_data, | |||
| ulint | col_len, | |||
| ulint | comp | |||
| ) |
Definition at line 242 of file row0mysql.c.
References DATA_INT, DATA_UNSIGNED, dfield_get_type(), dtype_struct::mtype, and dtype_struct::prtype.
Referenced by row_sel_convert_mysql_key_to_innobase().
00244 : up to which byte we used 00245 buf in the conversion */ 00246 dfield_t* dfield, /* in/out: dfield where dtype 00247 information must be already set when 00248 this function is called! */ 00249 byte* buf, /* in/out: buffer for a converted 00250 integer value; this must be at least 00251 col_len long then! */ 00252 ibool row_format_col, /* TRUE if the mysql_data is from 00253 a MySQL row, FALSE if from a MySQL 00254 key value; 00255 in MySQL, a true VARCHAR storage 00256 format differs in a row and in a 00257 key value: in a key value the length 00258 is always stored in 2 bytes! */ 00259 byte* mysql_data, /* in: MySQL column value, not 00260 SQL NULL; NOTE that dfield may also 00261 get a pointer to mysql_data, 00262 therefore do not discard this as long 00263 as dfield is used! */ 00264 ulint col_len, /* in: MySQL column length; NOTE that 00265 this is the storage length of the 00266 column in the MySQL format row, not 00267 necessarily the length of the actual 00268 payload data; if the column is a true 00269 VARCHAR then this is irrelevant */ 00270 ulint comp) /* in: nonzero=compact format */ 00271 { 00272 byte* ptr = mysql_data; 00273 dtype_t* dtype; 00274 ulint type; 00275 ulint lenlen; 00276 00277 dtype = dfield_get_type(dfield); 00278 00279 type = dtype->mtype; 00280 00281 if (type == DATA_INT) { 00282 /* Store integer data in Innobase in a big-endian format, 00283 sign bit negated if the data is a signed integer. In MySQL, 00284 integers are stored in a little-endian format. */ 00285 00286 ptr = buf + col_len; 00287 00288 for (;;) { 00289 ptr--; 00290 *ptr = *mysql_data; 00291 if (ptr == buf) { 00292 break; 00293 } 00294 mysql_data++; 00295 } 00296 00297 if (!(dtype->prtype & DATA_UNSIGNED)) { 00298 00299 *ptr = (byte) (*ptr ^ 128); 00300 } 00301 00302 buf += col_len; 00303 } else if ((type == DATA_VARCHAR 00304 || type == DATA_VARMYSQL 00305 || type == DATA_BINARY)) { 00306 00307 if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) { 00308 /* The length of the actual data is stored to 1 or 2 00309 bytes at the start of the field */ 00310 00311 if (row_format_col) { 00312 if (dtype->prtype & DATA_LONG_TRUE_VARCHAR) { 00313 lenlen = 2; 00314 } else { 00315 lenlen = 1; 00316 } 00317 } else { 00318 /* In a MySQL key value, lenlen is always 2 */ 00319 lenlen = 2; 00320 } 00321 00322 ptr = row_mysql_read_true_varchar(&col_len, mysql_data, 00323 lenlen); 00324 } else { 00325 /* Remove trailing spaces from old style VARCHAR 00326 columns. */ 00327 00328 /* Handle UCS2 strings differently. */ 00329 ulint mbminlen = dtype_get_mbminlen(dtype); 00330 00331 ptr = mysql_data; 00332 00333 if (mbminlen == 2) { 00334 /* space=0x0020 */ 00335 /* Trim "half-chars", just in case. */ 00336 col_len &= ~1; 00337 00338 while (col_len >= 2 && ptr[col_len - 2] == 0x00 00339 && ptr[col_len - 1] == 0x20) { 00340 col_len -= 2; 00341 } 00342 } else { 00343 ut_a(mbminlen == 1); 00344 /* space=0x20 */ 00345 while (col_len > 0 00346 && ptr[col_len - 1] == 0x20) { 00347 col_len--; 00348 } 00349 } 00350 } 00351 } else if (comp && type == DATA_MYSQL 00352 && dtype_get_mbminlen(dtype) == 1 00353 && dtype_get_mbmaxlen(dtype) > 1) { 00354 /* In some cases we strip trailing spaces from UTF-8 and other 00355 multibyte charsets, from FIXED-length CHAR columns, to save 00356 space. UTF-8 would otherwise normally use 3 * the string length 00357 bytes to store a latin1 string! */ 00358 00359 /* We assume that this CHAR field is encoded in a 00360 variable-length character set where spaces have 00361 1:1 correspondence to 0x20 bytes, such as UTF-8. 00362 00363 Consider a CHAR(n) field, a field of n characters. 00364 It will contain between n * mbminlen and n * mbmaxlen bytes. 00365 We will try to truncate it to n bytes by stripping 00366 space padding. If the field contains single-byte 00367 characters only, it will be truncated to n characters. 00368 Consider a CHAR(5) field containing the string ".a " 00369 where "." denotes a 3-byte character represented by 00370 the bytes "$%&". After our stripping, the string will 00371 be stored as "$%&a " (5 bytes). The string ".abc " 00372 will be stored as "$%&abc" (6 bytes). 00373 00374 The space padding will be restored in row0sel.c, function 00375 row_sel_field_store_in_mysql_format(). */ 00376 00377 ulint n_chars; 00378 00379 ut_a(!(dtype_get_len(dtype) % dtype_get_mbmaxlen(dtype))); 00380 00381 n_chars = dtype_get_len(dtype) / dtype_get_mbmaxlen(dtype); 00382 00383 /* Strip space padding. */ 00384 while (col_len > n_chars && ptr[col_len - 1] == 0x20) { 00385 col_len--; 00386 } 00387 } else if (type == DATA_BLOB && row_format_col) { 00388 00389 ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len); 00390 } 00391 00392 dfield_set_data(dfield, ptr, col_len); 00393 00394 return(buf); 00395 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 128 of file row0mysql.c.
References mach_write_to_1(), mach_write_to_2_little_endian(), and ut_a.
00130 : pointer to the data, we skip the 1 or 2 bytes 00131 at the start that are used to store the len */ 00132 byte* dest, /* in: where to store */ 00133 ulint len, /* in: length, must fit in two bytes */ 00134 ulint lenlen) /* in: storage length of len: either 1 or 2 bytes */ 00135 { 00136 if (lenlen == 2) { 00137 ut_a(len < 256 * 256); 00138 00139 mach_write_to_2_little_endian(dest, len); 00140 00141 return(dest + 2); 00142 } 00143 00144 ut_a(lenlen == 1); 00145 ut_a(len < 256); 00146 00147 mach_write_to_1(dest, len); 00148 00149 return(dest + 1); 00150 }
Here is the call graph for this function:

| void row_mysql_unfreeze_data_dictionary | ( | trx_t * | trx | ) |
Definition at line 1724 of file row0mysql.c.
References dict_operation_lock, trx_struct::dict_operation_lock_mode, rw_lock_s_unlock, RW_S_LATCH, and ut_a.
Referenced by row_ins_check_foreign_constraints(), row_purge(), row_purge_parse_undo_rec(), row_undo(), row_upd_check_references_constraints(), row_upd_index_is_referenced(), and srv_suspend_mysql_thread().
01726 : transaction */ 01727 { 01728 ut_a(trx->dict_operation_lock_mode == RW_S_LATCH); 01729 01730 rw_lock_s_unlock(&dict_operation_lock); 01731 01732 trx->dict_operation_lock_mode = 0; 01733 }
Here is the caller graph for this function:

| void row_mysql_unlock_data_dictionary | ( | trx_t * | trx | ) |
Definition at line 1760 of file row0mysql.c.
References dict_operation_lock, trx_struct::dict_operation_lock_mode, dict_sys, dict_sys_struct::mutex, mutex_exit(), rw_lock_x_unlock, RW_X_LATCH, and ut_a.
Referenced by dict_create_or_check_foreign_constraint_tables(), row_discard_tablespace_for_mysql(), row_drop_database_for_mysql(), row_drop_table_for_mysql(), row_import_tablespace_for_mysql(), row_rename_table_for_mysql(), row_truncate_table_for_mysql(), and trx_rollback_or_clean_all_without_sess().
01762 : transaction */ 01763 { 01764 ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); 01765 01766 /* Serialize data dictionary operations with dictionary mutex: 01767 no deadlocks can occur then in these operations */ 01768 01769 mutex_exit(&(dict_sys->mutex)); 01770 rw_lock_x_unlock(&dict_operation_lock); 01771 01772 trx->dict_operation_lock_mode = 0; 01773 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_prebuild_sel_graph | ( | row_prebuilt_t * | prebuilt | ) |
Definition at line 1191 of file row0mysql.c.
References row_prebuilt_struct::heap, NULL, pars_complete_graph_for_exec(), QUE_FORK_ACTIVE, que_node_get_parent(), row_prebuilt_struct::sel_graph, sel_node_create(), que_fork_struct::state, row_prebuilt_struct::trx, and ut_ad.
Referenced by row_lock_table_for_mysql(), and row_search_for_mysql().
01193 : prebuilt struct in MySQL 01194 handle */ 01195 { 01196 sel_node_t* node; 01197 01198 ut_ad(prebuilt && prebuilt->trx); 01199 01200 if (prebuilt->sel_graph == NULL) { 01201 01202 node = sel_node_create(prebuilt->heap); 01203 01204 prebuilt->sel_graph = 01205 que_node_get_parent( 01206 pars_complete_graph_for_exec(node, 01207 prebuilt->trx, 01208 prebuilt->heap)); 01209 01210 prebuilt->sel_graph->state = QUE_FORK_ACTIVE; 01211 } 01212 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_prebuilt_free | ( | row_prebuilt_t * | prebuilt | ) |
Definition at line 670 of file row0mysql.c.
References row_prebuilt_struct::blob_heap, btr_pcur_free_for_mysql(), row_prebuilt_struct::clust_pcur, row_prebuilt_struct::fetch_cache, row_prebuilt_struct::ins_graph, mach_read_from_4(), row_prebuilt_struct::magic_n, row_prebuilt_struct::magic_n2, mem_analyze_corruption(), mem_free, mem_heap_free, MYSQL_FETCH_CACHE_SIZE, row_prebuilt_struct::mysql_row_len, row_prebuilt_struct::mysql_template, dict_table_struct::name, NULL, row_prebuilt_struct::old_vers_heap, row_prebuilt_struct::pcur, que_graph_free_recursive(), ROW_PREBUILT_ALLOCATED, ROW_PREBUILT_FETCH_MAGIC_N, ROW_PREBUILT_FREED, row_prebuilt_struct::sel_graph, row_prebuilt_struct::table, TRUE, row_prebuilt_struct::upd_graph, ut_error, and ut_print_name().
00672 : prebuilt struct */ 00673 { 00674 ulint i; 00675 00676 if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED 00677 || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) { 00678 fprintf(stderr, 00679 "InnoDB: Error: trying to free a corrupt\n" 00680 "InnoDB: table handle. Magic n %lu, magic n2 %lu, table name", 00681 (ulong) prebuilt->magic_n, 00682 (ulong) prebuilt->magic_n2); 00683 ut_print_name(stderr, NULL, TRUE, prebuilt->table->name); 00684 putc('\n', stderr); 00685 00686 mem_analyze_corruption(prebuilt); 00687 00688 ut_error; 00689 } 00690 00691 prebuilt->magic_n = ROW_PREBUILT_FREED; 00692 prebuilt->magic_n2 = ROW_PREBUILT_FREED; 00693 00694 btr_pcur_free_for_mysql(prebuilt->pcur); 00695 btr_pcur_free_for_mysql(prebuilt->clust_pcur); 00696 00697 if (prebuilt->mysql_template) { 00698 mem_free(prebuilt->mysql_template); 00699 } 00700 00701 if (prebuilt->ins_graph) { 00702 que_graph_free_recursive(prebuilt->ins_graph); 00703 } 00704 00705 if (prebuilt->sel_graph) { 00706 que_graph_free_recursive(prebuilt->sel_graph); 00707 } 00708 00709 if (prebuilt->upd_graph) { 00710 que_graph_free_recursive(prebuilt->upd_graph); 00711 } 00712 00713 if (prebuilt->blob_heap) { 00714 mem_heap_free(prebuilt->blob_heap); 00715 } 00716 00717 if (prebuilt->old_vers_heap) { 00718 mem_heap_free(prebuilt->old_vers_heap); 00719 } 00720 00721 for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) { 00722 if (prebuilt->fetch_cache[i] != NULL) { 00723 00724 if ((ROW_PREBUILT_FETCH_MAGIC_N != 00725 mach_read_from_4((prebuilt->fetch_cache[i]) - 4)) 00726 || (ROW_PREBUILT_FETCH_MAGIC_N != 00727 mach_read_from_4((prebuilt->fetch_cache[i]) 00728 + prebuilt->mysql_row_len))) { 00729 fputs( 00730 "InnoDB: Error: trying to free a corrupt\n" 00731 "InnoDB: fetch buffer.\n", stderr); 00732 00733 mem_analyze_corruption( 00734 prebuilt->fetch_cache[i]); 00735 00736 ut_error; 00737 } 00738 00739 mem_free((prebuilt->fetch_cache[i]) - 4); 00740 } 00741 } 00742 00743 dict_table_decrement_handle_count(prebuilt->table); 00744 00745 mem_heap_free(prebuilt->heap); 00746 }
Here is the call graph for this function:

| int row_rename_table_for_mysql | ( | const char * | old_name, | |
| const char * | new_name, | |||
| trx_t * | trx | |||
| ) |
Definition at line 3486 of file row0mysql.c.
References trx_struct::check_foreigns, DB_DUPLICATE_KEY, DB_ERROR, DB_SUCCESS, DB_TABLE_NOT_FOUND, dict_foreign_parse_drop_constraints(), dict_get_db_name_len(), dict_load_foreigns(), dict_table_get_low(), dict_table_rename_in_cache(), err, trx_struct::error_state, FALSE, dict_table_struct::ibd_file_missing, info, mem_heap_create, mem_heap_free, mem_heap_strdupl(), trx_struct::mysql_thread_id, NULL, trx_struct::op_info, os_thread_get_curr_id(), pars_info_add_str_literal(), pars_info_create(), que_eval_sql(), row_delete_constraint(), row_is_mysql_tmp_table_name(), row_mysql_is_system_table(), row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary(), srv_created_new_raw, srv_force_recovery, TRUE, trx_commit_for_mysql(), trx_general_rollback_for_mysql(), trx_start_if_not_started(), ut_a, ut_ad, ut_print_name(), and ut_print_timestamp().
Referenced by row_mysql_recover_tmp_table().
03488 : error code or DB_SUCCESS */ 03489 const char* old_name, /* in: old table name */ 03490 const char* new_name, /* in: new table name */ 03491 trx_t* trx) /* in: transaction handle */ 03492 { 03493 dict_table_t* table; 03494 ulint err; 03495 mem_heap_t* heap = NULL; 03496 const char** constraints_to_drop = NULL; 03497 ulint n_constraints_to_drop = 0; 03498 ibool recovering_temp_table = FALSE; 03499 ibool old_is_tmp, new_is_tmp; 03500 pars_info_t* info = NULL; 03501 03502 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 03503 ut_a(old_name != NULL); 03504 ut_a(new_name != NULL); 03505 03506 if (srv_created_new_raw || srv_force_recovery) { 03507 fputs( 03508 "InnoDB: A new raw disk partition was initialized or\n" 03509 "InnoDB: innodb_force_recovery is on: we do not allow\n" 03510 "InnoDB: database modifications by the user. Shut down\n" 03511 "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" 03512 "InnoDB: with raw, and innodb_force_... is removed.\n", 03513 stderr); 03514 03515 trx_commit_for_mysql(trx); 03516 return(DB_ERROR); 03517 } 03518 03519 if (row_mysql_is_system_table(new_name)) { 03520 03521 fprintf(stderr, 03522 "InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n" 03523 "InnoDB: MySQL system tables must be of the MyISAM type!\n", 03524 new_name); 03525 03526 trx_commit_for_mysql(trx); 03527 return(DB_ERROR); 03528 } 03529 03530 trx->op_info = "renaming table"; 03531 trx_start_if_not_started(trx); 03532 03533 old_is_tmp = row_is_mysql_tmp_table_name(old_name); 03534 new_is_tmp = row_is_mysql_tmp_table_name(new_name); 03535 03536 if (row_mysql_is_recovered_tmp_table(new_name)) { 03537 03538 recovering_temp_table = TRUE; 03539 } else { 03540 /* Serialize data dictionary operations with dictionary mutex: 03541 no deadlocks can occur then in these operations */ 03542 03543 row_mysql_lock_data_dictionary(trx); 03544 } 03545 03546 table = dict_table_get_low(old_name); 03547 03548 if (!table) { 03549 err = DB_TABLE_NOT_FOUND; 03550 ut_print_timestamp(stderr); 03551 03552 fputs(" InnoDB: Error: table ", stderr); 03553 ut_print_name(stderr, trx, TRUE, old_name); 03554 fputs(" does not exist in the InnoDB internal\n" 03555 "InnoDB: data dictionary though MySQL is trying to rename the table.\n" 03556 "InnoDB: Have you copied the .frm file of the table to the\n" 03557 "InnoDB: MySQL database directory from another database?\n" 03558 "InnoDB: You can look for further help from\n" 03559 "InnoDB: http://dev.mysql.com/doc/mysql/en/" 03560 "InnoDB_troubleshooting_datadict.html\n", stderr); 03561 goto funct_exit; 03562 } 03563 03564 if (table->ibd_file_missing) { 03565 err = DB_TABLE_NOT_FOUND; 03566 ut_print_timestamp(stderr); 03567 03568 fputs(" InnoDB: Error: table ", stderr); 03569 ut_print_name(stderr, trx, TRUE, old_name); 03570 fputs( 03571 " does not have an .ibd file in the database directory.\n" 03572 "InnoDB: You can look for further help from\n" 03573 "InnoDB: http://dev.mysql.com/doc/mysql/en/" 03574 "InnoDB_troubleshooting_datadict.html\n", stderr); 03575 goto funct_exit; 03576 } 03577 03578 if (new_is_tmp) { 03579 /* MySQL is doing an ALTER TABLE command and it renames the 03580 original table to a temporary table name. We want to preserve 03581 the original foreign key constraint definitions despite the 03582 name change. An exception is those constraints for which 03583 the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/ 03584 03585 heap = mem_heap_create(100); 03586 03587 err = dict_foreign_parse_drop_constraints(heap, trx, 03588 table, &n_constraints_to_drop, &constraints_to_drop); 03589 03590 if (err != DB_SUCCESS) { 03591 03592 goto funct_exit; 03593 } 03594 } 03595 03596 /* We use the private SQL parser of Innobase to generate the query 03597 graphs needed in deleting the dictionary data from system tables in 03598 Innobase. Deleting a row from SYS_INDEXES table also frees the file 03599 segments of the B-tree associated with the index. */ 03600 03601 info = pars_info_create(); 03602 03603 pars_info_add_str_literal(info, "new_table_name", new_name); 03604 pars_info_add_str_literal(info, "old_table_name", old_name); 03605 03606 err = que_eval_sql(info, 03607 "PROCEDURE RENAME_TABLE () IS\n" 03608 "BEGIN\n" 03609 "UPDATE SYS_TABLES SET NAME = :new_table_name\n" 03610 " WHERE NAME = :old_table_name;\n" 03611 "END;\n" 03612 , FALSE, trx); 03613 03614 if (err != DB_SUCCESS) { 03615 03616 goto end; 03617 } 03618 03619 if (!new_is_tmp) { 03620 /* Rename all constraints. */ 03621 03622 info = pars_info_create(); 03623 03624 pars_info_add_str_literal(info, "new_table_name", new_name); 03625 pars_info_add_str_literal(info, "old_table_name", old_name); 03626 03627 err = que_eval_sql(info, 03628 "PROCEDURE RENAME_CONSTRAINT_IDS () IS\n" 03629 "gen_constr_prefix CHAR;\n" 03630 "new_db_name CHAR;\n" 03631 "foreign_id CHAR;\n" 03632 "new_foreign_id CHAR;\n" 03633 "old_db_name_len INT;\n" 03634 "old_t_name_len INT;\n" 03635 "new_db_name_len INT;\n" 03636 "id_len INT;\n" 03637 "found INT;\n" 03638 "BEGIN\n" 03639 "found := 1;\n" 03640 "old_db_name_len := INSTR(:old_table_name, '/') - 1;\n" 03641 "new_db_name_len := INSTR(:new_table_name, '/') - 1;\n" 03642 "new_db_name := SUBSTR(:new_table_name, 0, new_db_name_len);\n" 03643 "old_t_name_len := LENGTH(:old_table_name);\n" 03644 "gen_constr_prefix := CONCAT(:old_table_name, '_ibfk_');\n" 03645 "WHILE found = 1 LOOP\n" 03646 " SELECT ID INTO foreign_id\n" 03647 " FROM SYS_FOREIGN\n" 03648 " WHERE FOR_NAME = :old_table_name\n" 03649 " AND TO_BINARY(FOR_NAME) = TO_BINARY(:old_table_name)\n" 03650 " LOCK IN SHARE MODE;\n" 03651 " IF (SQL % NOTFOUND) THEN\n" 03652 " found := 0;\n" 03653 " ELSE\n" 03654 " UPDATE SYS_FOREIGN\n" 03655 " SET FOR_NAME = :new_table_name\n" 03656 " WHERE ID = foreign_id;\n" 03657 " id_len := LENGTH(foreign_id);\n" 03658 " IF (INSTR(foreign_id, '/') > 0) THEN\n" 03659 " IF (INSTR(foreign_id,\n" 03660 " gen_constr_prefix) > 0)\n" 03661 " THEN\n" 03662 " new_foreign_id :=\n" 03663 " CONCAT(:new_table_name,\n" 03664 " SUBSTR(foreign_id, old_t_name_len,\n" 03665 " id_len - old_t_name_len));\n" 03666 " ELSE\n" 03667 " new_foreign_id :=\n" 03668 " CONCAT(new_db_name,\n" 03669 " SUBSTR(foreign_id,\n" 03670 " old_db_name_len,\n" 03671 " id_len - old_db_name_len));\n" 03672 " END IF;\n" 03673 " UPDATE SYS_FOREIGN\n" 03674 " SET ID = new_foreign_id\n" 03675 " WHERE ID = foreign_id;\n" 03676 " UPDATE SYS_FOREIGN_COLS\n" 03677 " SET ID = new_foreign_id\n" 03678 " WHERE ID = foreign_id;\n" 03679 " END IF;\n" 03680 " END IF;\n" 03681 "END LOOP;\n" 03682 "UPDATE SYS_FOREIGN SET REF_NAME = :new_table_name\n" 03683 "WHERE REF_NAME = :old_table_name\n" 03684 " AND TO_BINARY(REF_NAME) = TO_BINARY(:old_table_name);\n" 03685 "END;\n" 03686 , FALSE, trx); 03687 03688 } else if (n_constraints_to_drop > 0) { 03689 /* Drop some constraints of tmp tables. */ 03690 03691 ulint db_name_len = dict_get_db_name_len(old_name) + 1; 03692 char* db_name = mem_heap_strdupl(heap, old_name, 03693 db_name_len); 03694 ulint i; 03695 03696 for (i = 0; i < n_constraints_to_drop; i++) { 03697 err = row_delete_constraint(constraints_to_drop[i], 03698 db_name, heap, trx); 03699 03700 if (err != DB_SUCCESS) { 03701 break; 03702 } 03703 } 03704 } 03705 03706 end: 03707 if (err != DB_SUCCESS) { 03708 if (err == DB_DUPLICATE_KEY) { 03709 ut_print_timestamp(stderr); 03710 fputs( 03711 " InnoDB: Error; possible reasons:\n" 03712 "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n" 03713 "InnoDB: to have the same internal name in case-insensitive comparison.\n" 03714 "InnoDB: 2) table ", stderr); 03715 ut_print_name(stderr, trx, TRUE, new_name); 03716 fputs(" exists in the InnoDB internal data\n" 03717 "InnoDB: dictionary though MySQL is trying rename table ", stderr); 03718 ut_print_name(stderr, trx, TRUE, old_name); 03719 fputs(" to it.\n" 03720 "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" 03721 "InnoDB: You can look for further help from\n" 03722 "InnoDB: http://dev.mysql.com/doc/mysql/en/" 03723 "InnoDB_troubleshooting_datadict.html\n" 03724 "InnoDB: If table ", stderr); 03725 ut_print_name(stderr, trx, TRUE, new_name); 03726 fputs( 03727 " is a temporary table #sql..., then it can be that\n" 03728 "InnoDB: there are still queries running on the table, and it will be\n" 03729 "InnoDB: dropped automatically when the queries end.\n" 03730 "InnoDB: You can drop the orphaned table inside InnoDB by\n" 03731 "InnoDB: creating an InnoDB table with the same name in another\n" 03732 "InnoDB: database and copying the .frm file to the current database.\n" 03733 "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" 03734 "InnoDB: succeed.\n", stderr); 03735 } 03736 trx->error_state = DB_SUCCESS; 03737 trx_general_rollback_for_mysql(trx, FALSE, NULL); 03738 trx->error_state = DB_SUCCESS; 03739 } else { 03740 /* The following call will also rename the .ibd data file if 03741 the table is stored in a single-table tablespace */ 03742 03743 ibool success = dict_table_rename_in_cache(table, new_name, 03744 !new_is_tmp); 03745 03746 if (!success) { 03747 trx->error_state = DB_SUCCESS; 03748 trx_general_rollback_for_mysql(trx, FALSE, NULL); 03749 trx->error_state = DB_SUCCESS; 03750 ut_print_timestamp(stderr); 03751 fputs(" InnoDB: Error in table rename, cannot rename ", 03752 stderr); 03753 ut_print_name(stderr, trx, TRUE, old_name); 03754 fputs(" to ", stderr); 03755 ut_print_name(stderr, trx, TRUE, new_name); 03756 putc('\n', stderr); 03757 err = DB_ERROR; 03758 03759 goto funct_exit; 03760 } 03761 03762 /* We only want to switch off some of the type checking in 03763 an ALTER, not in a RENAME. */ 03764 03765 err = dict_load_foreigns(new_name, 03766 old_is_tmp ? trx->check_foreigns : TRUE); 03767 03768 if (err != DB_SUCCESS) { 03769 ut_print_timestamp(stderr); 03770 03771 if (old_is_tmp) { 03772 fputs(" InnoDB: Error: in ALTER TABLE ", 03773 stderr); 03774 ut_print_name(stderr, trx, TRUE, new_name); 03775 fputs("\n" 03776 "InnoDB: has or is referenced in foreign key constraints\n" 03777 "InnoDB: which are not compatible with the new table definition.\n", 03778 stderr); 03779 } else { 03780 fputs( 03781 " InnoDB: Error: in RENAME TABLE table ", 03782 stderr); 03783 ut_print_name(stderr, trx, TRUE, new_name); 03784 fputs("\n" 03785 "InnoDB: is referenced in foreign key constraints\n" 03786 "InnoDB: which are not compatible with the new table definition.\n", 03787 stderr); 03788 } 03789 03790 ut_a(dict_table_rename_in_cache(table, 03791 old_name, FALSE)); 03792 trx->error_state = DB_SUCCESS; 03793 trx_general_rollback_for_mysql(trx, FALSE, NULL); 03794 trx->error_state = DB_SUCCESS; 03795 } 03796 } 03797 03798 funct_exit: 03799 trx_commit_for_mysql(trx); 03800 03801 if (!recovering_temp_table) { 03802 row_mysql_unlock_data_dictionary(trx); 03803 } 03804 03805 if (UNIV_LIKELY_NULL(heap)) { 03806 mem_heap_free(heap); 03807 } 03808 03809 trx->op_info = ""; 03810 03811 return((int) err); 03812 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int row_table_add_foreign_constraints | ( | trx_t * | trx, | |
| const char * | sql_string, | |||
| const char * | name, | |||
| ibool | reject_fks | |||
| ) |
Definition at line 2117 of file row0mysql.c.
References DB_SUCCESS, dict_create_foreign_constraints(), dict_load_foreigns(), trx_struct::dict_operation, dict_operation_lock, dict_sys, err, trx_struct::error_state, FALSE, dict_sys_struct::mutex, NULL, trx_struct::op_info, row_drop_table_for_mysql(), RW_LOCK_EX, TRUE, trx_general_rollback_for_mysql(), trx_start_if_not_started(), ut_a, and ut_ad.
02119 : error code or DB_SUCCESS */ 02120 trx_t* trx, /* in: transaction */ 02121 const char* sql_string, /* in: table create statement where 02122 foreign keys are declared like: 02123 FOREIGN KEY (a, b) REFERENCES table2(c, d), 02124 table2 can be written also with the 02125 database name before it: test.table2 */ 02126 const char* name, /* in: table full name in the 02127 normalized form 02128 database_name/table_name */ 02129 ibool reject_fks) /* in: if TRUE, fail with error 02130 code DB_CANNOT_ADD_CONSTRAINT if 02131 any foreign keys are found. */ 02132 { 02133 ulint err; 02134 02135 #ifdef UNIV_SYNC_DEBUG 02136 ut_ad(mutex_own(&(dict_sys->mutex))); 02137 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); 02138 #endif /* UNIV_SYNC_DEBUG */ 02139 ut_a(sql_string); 02140 02141 trx->op_info = "adding foreign keys"; 02142 02143 trx_start_if_not_started(trx); 02144 02145 if (row_mysql_is_recovered_tmp_table(name)) { 02146 02147 return(DB_SUCCESS); 02148 } 02149 02150 trx->dict_operation = TRUE; 02151 02152 err = dict_create_foreign_constraints(trx, sql_string, name, 02153 reject_fks); 02154 02155 if (err == DB_SUCCESS) { 02156 /* Check that also referencing constraints are ok */ 02157 err = dict_load_foreigns(name, TRUE); 02158 } 02159 02160 if (err != DB_SUCCESS) { 02161 /* We have special error handling here */ 02162 02163 trx->error_state = DB_SUCCESS; 02164 02165 trx_general_rollback_for_mysql(trx, FALSE, NULL); 02166 02167 row_drop_table_for_mysql(name, trx, FALSE); 02168 02169 trx->error_state = DB_SUCCESS; 02170 } 02171 02172 return((int) err); 02173 }
Here is the call graph for this function:

| ibool row_table_got_default_clust_index | ( | dict_table_t * | table | ) |
Definition at line 1616 of file row0mysql.c.
References DATA_SYS, dict_index_get_nth_type(), dict_table_get_first_index(), dtype_get_mtype(), FALSE, and TRUE.
Referenced by row_get_mysql_key_number_for_index().
01619 { 01620 dict_index_t* clust_index; 01621 01622 clust_index = dict_table_get_first_index(table); 01623 01624 if (dtype_get_mtype(dict_index_get_nth_type(clust_index, 0)) 01625 == DATA_SYS) { 01626 return(TRUE); 01627 } 01628 01629 return(FALSE); 01630 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int row_truncate_table_for_mysql | ( | dict_table_t * | table, | |
| trx_t * | trx | |||
| ) |
Definition at line 2692 of file row0mysql.c.
References BTR_MODIFY_LEAF, btr_pcur_close(), btr_pcur_get_rec(), btr_pcur_is_on_user_rec(), btr_pcur_move_to_next_user_rec(), btr_pcur_open_on_user_rec(), btr_pcur_restore_position(), btr_pcur_store_position(), buf, trx_struct::check_foreigns, DB_ERROR, DB_SUCCESS, dfield_set_data(), dict_foreign_err_file, dict_foreign_err_mutex, dict_hdr_get_new_id(), DICT_HDR_TABLE_ID, dict_index_copy_types(), dict_operation_lock, trx_struct::dict_operation_lock_mode, dict_sys, DICT_SYS_INDEXES_PAGE_NO_FIELD, dict_table_autoinc_initialize(), dict_table_change_id_in_cache(), dict_table_get_first_index(), dict_truncate_index_tree(), dict_update_statistics(), dtuple_create(), dtuple_get_nth_field(), err, trx_struct::error_state, FALSE, FIL_NULL, dict_foreign_struct::foreign_table, dict_foreign_struct::foreign_table_name, dict_table_struct::id, info, lock_reset_all_on_table(), mach_write_to_8(), mem_heap_alloc(), mem_heap_create, mem_heap_free, memcmp(), mtr_commit(), mtr_start(), dict_sys_struct::mutex, mutex_enter, mutex_exit(), trx_struct::mysql_thread_id, dict_table_struct::n_foreign_key_checks_running, dict_table_struct::name, NULL, trx_struct::op_info, os_thread_get_curr_id(), PAGE_CUR_GE, page_rec_write_index_page_no(), pars_info_add_dulint_literal(), pars_info_create(), que_eval_sql(), rec_get_deleted_flag(), rec_get_nth_field_old(), dict_table_struct::referenced_list, row_mysql_lock_data_dictionary(), row_mysql_unlock_data_dictionary(), RW_LOCK_EX, srv_created_new_raw, srv_wake_master_thread(), dict_sys_struct::sys_indexes, trx_struct::table_id, TRUE, trx_commit_for_mysql(), trx_general_rollback_for_mysql(), trx_start_if_not_started(), ut_a, ut_ad, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, ut_print_name(), and ut_print_timestamp().
02694 : error code or DB_SUCCESS */ 02695 dict_table_t* table, /* in: table handle */ 02696 trx_t* trx) /* in: transaction handle */ 02697 { 02698 dict_foreign_t* foreign; 02699 ulint err; 02700 mem_heap_t* heap; 02701 byte* buf; 02702 dtuple_t* tuple; 02703 dfield_t* dfield; 02704 dict_index_t* sys_index; 02705 btr_pcur_t pcur; 02706 mtr_t mtr; 02707 dulint new_id; 02708 pars_info_t* info = NULL; 02709 02710 /* How do we prevent crashes caused by ongoing operations on the table? Old 02711 operations could try to access non-existent pages. 02712 02713 1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock 02714 on the table before we can do TRUNCATE TABLE. Then there are no running 02715 queries on the table. This is guaranteed, because in 02716 ha_innobase::store_lock(), we do not weaken the TL_WRITE lock requested 02717 by MySQL when executing SQLCOM_TRUNCATE. 02718 2) Purge and rollback: we assign a new table id for the table. Since purge and 02719 rollback look for the table based on the table id, they see the table as 02720 'dropped' and discard their operations. 02721 3) Insert buffer: TRUNCATE TABLE is analogous to DROP TABLE, so we do not 02722 have to remove insert buffer records, as the insert buffer works at a low 02723 level. If a freed page is later reallocated, the allocator will remove 02724 the ibuf entries for it. 02725 02726 TODO: when we truncate *.ibd files (analogous to DISCARD TABLESPACE), we 02727 will have to remove we remove all entries for the table in the insert 02728 buffer tree! 02729 02730 4) Linear readahead and random readahead: we use the same method as in 3) to 02731 discard ongoing operations. (This will only be relevant for TRUNCATE TABLE 02732 by DISCARD TABLESPACE.) 02733 5) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0, we 02734 do not allow the TRUNCATE. We also reserve the data dictionary latch. */ 02735 02736 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 02737 ut_ad(table); 02738 02739 if (srv_created_new_raw) { 02740 fputs( 02741 "InnoDB: A new raw disk partition was initialized or\n" 02742 "InnoDB: innodb_force_recovery is on: we do not allow\n" 02743 "InnoDB: database modifications by the user. Shut down\n" 02744 "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" 02745 "InnoDB: with raw, and innodb_force_... is removed.\n", 02746 stderr); 02747 02748 return(DB_ERROR); 02749 } 02750 02751 trx->op_info = "truncating table"; 02752 02753 trx_start_if_not_started(trx); 02754 02755 /* Serialize data dictionary operations with dictionary mutex: 02756 no deadlocks can occur then in these operations */ 02757 02758 ut_a(trx->dict_operation_lock_mode == 0); 02759 /* Prevent foreign key checks etc. while we are truncating the 02760 table */ 02761 02762 row_mysql_lock_data_dictionary(trx); 02763 02764 #ifdef UNIV_SYNC_DEBUG 02765 ut_ad(mutex_own(&(dict_sys->mutex))); 02766 ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); 02767 #endif /* UNIV_SYNC_DEBUG */ 02768 02769 /* Check if the table is referenced by foreign key constraints from 02770 some other table (not the table itself) */ 02771 02772 foreign = UT_LIST_GET_FIRST(table->referenced_list); 02773 02774 while (foreign && foreign->foreign_table == table) { 02775 foreign = UT_LIST_GET_NEXT(referenced_list, foreign); 02776 } 02777 02778 if (foreign && trx->check_foreigns) { 02779 FILE* ef = dict_foreign_err_file; 02780 02781 /* We only allow truncating a referenced table if 02782 FOREIGN_KEY_CHECKS is set to 0 */ 02783 02784 mutex_enter(&dict_foreign_err_mutex); 02785 rewind(ef); 02786 ut_print_timestamp(ef); 02787 02788 fputs(" Cannot truncate table ", ef); 02789 ut_print_name(ef, trx, TRUE, table->name); 02790 fputs(" by DROP+CREATE\n" 02791 "InnoDB: because it is referenced by ", ef); 02792 ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); 02793 putc('\n', ef); 02794 mutex_exit(&dict_foreign_err_mutex); 02795 02796 err = DB_ERROR; 02797 goto funct_exit; 02798 } 02799 02800 /* TODO: could we replace the counter n_foreign_key_checks_running 02801 with lock checks on the table? Acquire here an exclusive lock on the 02802 table, and rewrite lock0lock.c and the lock wait in srv0srv.c so that 02803 they can cope with the table having been truncated here? Foreign key 02804 checks take an IS or IX lock on the table. */ 02805 02806 if (table->n_foreign_key_checks_running > 0) { 02807 ut_print_timestamp(stderr); 02808 fputs(" InnoDB: Cannot truncate table ", stderr); 02809 ut_print_name(stderr, trx, TRUE, table->name); 02810 fputs(" by DROP+CREATE\n" 02811 "InnoDB: because there is a foreign key check running on it.\n", 02812 stderr); 02813 err = DB_ERROR; 02814 02815 goto funct_exit; 02816 } 02817 02818 /* Remove any locks there are on the table or its records */ 02819 02820 lock_reset_all_on_table(table); 02821 02822 trx->table_id = table->id; 02823 02824 /* scan SYS_INDEXES for all indexes of the table */ 02825 heap = mem_heap_create(800); 02826 02827 tuple = dtuple_create(heap, 1); 02828 dfield = dtuple_get_nth_field(tuple, 0); 02829 02830 buf = mem_heap_alloc(heap, 8); 02831 mach_write_to_8(buf, table->id); 02832 02833 dfield_set_data(dfield, buf, 8); 02834 sys_index = dict_table_get_first_index(dict_sys->sys_indexes); 02835 dict_index_copy_types(tuple, sys_index, 1); 02836 02837 mtr_start(&mtr); 02838 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, 02839 BTR_MODIFY_LEAF, &pcur, &mtr); 02840 for (;;) { 02841 rec_t* rec; 02842 const byte* field; 02843 ulint len; 02844 ulint root_page_no; 02845 02846 if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { 02847 /* The end of SYS_INDEXES has been reached. */ 02848 break; 02849 } 02850 02851 rec = btr_pcur_get_rec(&pcur); 02852 02853 field = rec_get_nth_field_old(rec, 0, &len); 02854 ut_ad(len == 8); 02855 02856 if (memcmp(buf, field, len) != 0) { 02857 /* End of indexes for the table (TABLE_ID mismatch). */ 02858 break; 02859 } 02860 02861 if (rec_get_deleted_flag(rec, FALSE)) { 02862 /* The index has been dropped. */ 02863 goto next_rec; 02864 } 02865 02866 btr_pcur_store_position(&pcur, &mtr); 02867 02868 /* This call may commit and restart mtr. */ 02869 root_page_no = dict_truncate_index_tree(table, rec, &mtr); 02870 02871 btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr); 02872 rec = btr_pcur_get_rec(&pcur); 02873 02874 if (root_page_no != FIL_NULL) { 02875 page_rec_write_index_page_no(rec, 02876 DICT_SYS_INDEXES_PAGE_NO_FIELD, 02877 root_page_no, &mtr); 02878 /* We will need to commit and restart the 02879 mini-transaction in order to avoid deadlocks. 02880 The dict_truncate_index_tree() call has allocated 02881 a page in this mini-transaction, and the rest of 02882 this loop could latch another index page. */ 02883 mtr_commit(&mtr); 02884 mtr_start(&mtr); 02885 btr_pcur_restore_position(BTR_MODIFY_LEAF, 02886 &pcur, &mtr); 02887 } 02888 02889 next_rec: 02890 btr_pcur_move_to_next_user_rec(&pcur, &mtr); 02891 } 02892 02893 btr_pcur_close(&pcur); 02894 mtr_commit(&mtr); 02895 02896 mem_heap_free(heap); 02897 02898 new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); 02899 02900 info = pars_info_create(); 02901 02902 pars_info_add_dulint_literal(info, "old_id", table->id); 02903 pars_info_add_dulint_literal(info, "new_id", new_id); 02904 02905 err = que_eval_sql(info, 02906 "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n" 02907 "BEGIN\n" 02908 "UPDATE SYS_TABLES SET ID = :new_id\n" 02909 " WHERE ID = :old_id;\n" 02910 "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n" 02911 " WHERE TABLE_ID = :old_id;\n" 02912 "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n" 02913 " WHERE TABLE_ID = :old_id;\n" 02914 "COMMIT WORK;\n" 02915 "END;\n" 02916 , FALSE, trx); 02917 02918 if (err != DB_SUCCESS) { 02919 trx->error_state = DB_SUCCESS; 02920 trx_general_rollback_for_mysql(trx, FALSE, NULL); 02921 trx->error_state = DB_SUCCESS; 02922 ut_print_timestamp(stderr); 02923 fputs(" InnoDB: Unable to assign a new identifier to table ", stderr); 02924 ut_print_name(stderr, trx, TRUE, table->name); 02925 fputs("\n" 02926 "InnoDB: after truncating it. Background processes may corrupt the table!\n", 02927 stderr); 02928 err = DB_ERROR; 02929 } else { 02930 dict_table_change_id_in_cache(table, new_id); 02931 } 02932 02933 dict_table_autoinc_initialize(table, 0); 02934 dict_update_statistics(table); 02935 02936 trx_commit_for_mysql(trx); 02937 02938 funct_exit: 02939 02940 row_mysql_unlock_data_dictionary(trx); 02941 02942 trx->op_info = ""; 02943 02944 srv_wake_master_thread(); 02945 02946 return((int) err); 02947 }
Here is the call graph for this function:

| int row_unlock_for_mysql | ( | row_prebuilt_t * | prebuilt, | |
| ibool | has_latches_on_recs | |||
| ) |
Definition at line 1454 of file row0mysql.c.
References btr_pcur_get_btr_cur(), btr_pcur_get_rec(), btr_pcur_restore_position(), BTR_SEARCH_LEAF, row_prebuilt_struct::clust_pcur, DB_SUCCESS, DICT_CLUSTERED, index(), btr_cur_struct::index, trx_struct::isolation_level, lock_rec_unlock(), mtr_commit(), mtr_start(), trx_struct::mysql_thread_id, NULL, trx_struct::op_info, os_thread_get_curr_id(), row_prebuilt_struct::pcur, row_prebuilt_struct::select_lock_type, srv_locks_unsafe_for_binlog, row_prebuilt_struct::trx, TRX_ISO_READ_COMMITTED, trx_new_rec_locks_contain(), and ut_ad.
Referenced by row_search_for_mysql().
01456 : error code or DB_SUCCESS */ 01457 row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL 01458 handle */ 01459 ibool has_latches_on_recs)/* TRUE if called so that we have 01460 the latches on the records under pcur 01461 and clust_pcur, and we do not need to 01462 reposition the cursors. */ 01463 { 01464 dict_index_t* index; 01465 btr_pcur_t* pcur = prebuilt->pcur; 01466 btr_pcur_t* clust_pcur = prebuilt->clust_pcur; 01467 trx_t* trx = prebuilt->trx; 01468 rec_t* rec; 01469 mtr_t mtr; 01470 01471 ut_ad(prebuilt && trx); 01472 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 01473 01474 if (!(srv_locks_unsafe_for_binlog 01475 || trx->isolation_level == TRX_ISO_READ_COMMITTED)) { 01476 01477 fprintf(stderr, 01478 "InnoDB: Error: calling row_unlock_for_mysql though\n" 01479 "InnoDB: srv_locks_unsafe_for_binlog is FALSE and\n" 01480 "InnoDB: this session is not using READ COMMITTED isolation level.\n"); 01481 01482 return(DB_SUCCESS); 01483 } 01484 01485 trx->op_info = "unlock_row"; 01486 01487 index = btr_pcur_get_btr_cur(pcur)->index; 01488 01489 if (index != NULL && trx_new_rec_locks_contain(trx, index)) { 01490 01491 mtr_start(&mtr); 01492 01493 /* Restore the cursor position and find the record */ 01494 01495 if (!has_latches_on_recs) { 01496 btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr); 01497 } 01498 01499 rec = btr_pcur_get_rec(pcur); 01500 01501 lock_rec_unlock(trx, rec, prebuilt->select_lock_type); 01502 01503 mtr_commit(&mtr); 01504 01505 /* If the search was done through the clustered index, then 01506 we have not used clust_pcur at all, and we must NOT try to 01507 reset locks on clust_pcur. The values in clust_pcur may be 01508 garbage! */ 01509 01510 if (index->type & DICT_CLUSTERED) { 01511 01512 goto func_exit; 01513 } 01514 } 01515 01516 index = btr_pcur_get_btr_cur(clust_pcur)->index; 01517 01518 if (index != NULL && trx_new_rec_locks_contain(trx, index)) { 01519 01520 mtr_start(&mtr); 01521 01522 /* Restore the cursor position and find the record */ 01523 01524 if (!has_latches_on_recs) { 01525 btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur, 01526 &mtr); 01527 } 01528 01529 rec = btr_pcur_get_rec(clust_pcur); 01530 01531 lock_rec_unlock(trx, rec, prebuilt->select_lock_type); 01532 01533 mtr_commit(&mtr); 01534 } 01535 01536 func_exit: 01537 trx->op_info = ""; 01538 01539 return(DB_SUCCESS); 01540 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void row_unlock_table_autoinc_for_mysql | ( | trx_t * | trx | ) |
Definition at line 892 of file row0mysql.c.
References trx_struct::auto_inc_lock, and lock_table_unlock_auto_inc().
00894 : transaction */ 00895 { 00896 if (!trx->auto_inc_lock) { 00897 00898 return; 00899 } 00900 00901 lock_table_unlock_auto_inc(trx); 00902 }
Here is the call graph for this function:

| ulint row_update_cascade_for_mysql | ( | que_thr_t * | thr, | |
| upd_node_t * | node, | |||
| dict_table_t * | table | |||
| ) |
Definition at line 1546 of file row0mysql.c.
References DB_LOCK_WAIT, DB_SUCCESS, err, trx_struct::error_state, upd_node_struct::is_delete, que_thr_struct::prev_node, que_thr_stop_for_mysql(), row_upd_step(), row_update_statistics_if_needed(), que_thr_struct::run_node, srv_n_rows_deleted, srv_n_rows_updated, srv_suspend_mysql_thread(), dict_table_struct::stat_n_rows, and thr_get_trx().
01548 : error code or DB_SUCCESS */ 01549 que_thr_t* thr, /* in: query thread */ 01550 upd_node_t* node, /* in: update node used in the cascade 01551 or set null operation */ 01552 dict_table_t* table) /* in: table where we do the operation */ 01553 { 01554 ulint err; 01555 trx_t* trx; 01556 01557 trx = thr_get_trx(thr); 01558 run_again: 01559 thr->run_node = node; 01560 thr->prev_node = node; 01561 01562 row_upd_step(thr); 01563 01564 err = trx->error_state; 01565 01566 /* Note that the cascade node is a subnode of another InnoDB 01567 query graph node. We do a normal lock wait in this node, but 01568 all errors are handled by the parent node. */ 01569 01570 if (err == DB_LOCK_WAIT) { 01571 /* Handle lock wait here */ 01572 01573 que_thr_stop_for_mysql(thr); 01574 01575 srv_suspend_mysql_thread(thr); 01576 01577 /* Note that a lock wait may also end in a lock wait timeout, 01578 or this transaction is picked as a victim in selective 01579 deadlock resolution */ 01580 01581 if (trx->error_state != DB_SUCCESS) { 01582 01583 return(trx->error_state); 01584 } 01585 01586 /* Retry operation after a normal lock wait */ 01587 01588 goto run_again; 01589 } 01590 01591 if (err != DB_SUCCESS) { 01592 01593 return(err); 01594 } 01595 01596 if (node->is_delete) { 01597 if (table->stat_n_rows > 0) { 01598 table->stat_n_rows--; 01599 } 01600 01601 srv_n_rows_deleted++; 01602 } else { 01603 srv_n_rows_updated++; 01604 } 01605 01606 row_update_statistics_if_needed(table); 01607 01608 return(err); 01609 }
Here is the call graph for this function:

| int row_update_for_mysql | ( | byte * | mysql_rec, | |
| row_prebuilt_t * | prebuilt | |||
| ) |
Definition at line 1292 of file row0mysql.c.
References btr_pcur_struct::btr_cur, btr_pcur_copy_stored_position(), BTR_PCUR_ON, row_prebuilt_struct::clust_pcur, DB_ERROR, DB_RECORD_NOT_FOUND, DB_SUCCESS, dict_table_get_first_index(), err, trx_struct::error_state, dict_table_struct::ibd_file_missing, btr_cur_struct::index, upd_node_struct::is_delete, row_prebuilt_struct::magic_n, mem_analyze_corruption(), trx_struct::mysql_thread_id, dict_table_struct::name, trx_struct::op_info, os_thread_get_curr_id(), row_prebuilt_struct::pcur, upd_node_struct::pcur, que_thr_struct::prev_node, que_fork_get_first_thr(), QUE_THR_LOCK_NOLOCK, QUE_THR_LOCK_ROW, que_thr_move_to_run_state_for_mysql(), que_thr_stop_for_mysql(), que_thr_stop_for_mysql_no_error(), btr_pcur_struct::rel_pos, row_mysql_delay_if_needed(), row_mysql_handle_errors(), ROW_PREBUILT_ALLOCATED, row_upd_step(), row_update_statistics_if_needed(), que_thr_struct::run_node, row_prebuilt_struct::sql_stat_start, srv_created_new_raw, srv_force_recovery, srv_n_rows_deleted, srv_n_rows_updated, dict_table_struct::stat_n_rows, upd_node_struct::state, row_prebuilt_struct::table, TRUE, row_prebuilt_struct::trx, trx_savept_take(), trx_start_if_not_started(), row_prebuilt_struct::upd_graph, row_prebuilt_struct::upd_node, UPD_NODE_UPDATE_CLUSTERED, ut_a, ut_ad, ut_error, UT_NOT_USED, ut_print_name(), and ut_print_timestamp().
01294 : error code or DB_SUCCESS */ 01295 byte* mysql_rec, /* in: the row to be updated, in 01296 the MySQL format */ 01297 row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL 01298 handle */ 01299 { 01300 trx_savept_t savept; 01301 ulint err; 01302 que_thr_t* thr; 01303 ibool was_lock_wait; 01304 dict_index_t* clust_index; 01305 /* ulint ref_len; */ 01306 upd_node_t* node; 01307 dict_table_t* table = prebuilt->table; 01308 trx_t* trx = prebuilt->trx; 01309 01310 ut_ad(prebuilt && trx); 01311 ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); 01312 UT_NOT_USED(mysql_rec); 01313 01314 if (prebuilt->table->ibd_file_missing) { 01315 ut_print_timestamp(stderr); 01316 fprintf(stderr, " InnoDB: Error:\n" 01317 "InnoDB: MySQL is trying to use a table handle but the .ibd file for\n" 01318 "InnoDB: table %s does not exist.\n" 01319 "InnoDB: Have you deleted the .ibd file from the database directory under\n" 01320 "InnoDB: the MySQL datadir, or have you used DISCARD TABLESPACE?\n" 01321 "InnoDB: Look from\n" 01322 "http://dev.mysql.com/doc/mysql/en/InnoDB_troubleshooting_datadict.html\n" 01323 "InnoDB: how you can resolve the problem.\n", 01324 prebuilt->table->name); 01325 return(DB_ERROR); 01326 } 01327 01328 if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { 01329 fprintf(stderr, 01330 "InnoDB: Error: trying to free a corrupt\n" 01331 "InnoDB: table handle. Magic n %lu, table name", 01332 (ulong) prebuilt->magic_n); 01333 ut_print_name(stderr, prebuilt->trx, TRUE, 01334 prebuilt->table->name); 01335 putc('\n', stderr); 01336 01337 mem_analyze_corruption(prebuilt); 01338 01339 ut_error; 01340 } 01341 01342 if (srv_created_new_raw || srv_force_recovery) { 01343 fputs( 01344 "InnoDB: A new raw disk partition was initialized or\n" 01345 "InnoDB: innodb_force_recovery is on: we do not allow\n" 01346 "InnoDB: database modifications by the user. Shut down\n" 01347 "InnoDB: mysqld and edit my.cnf so that newraw is replaced\n" 01348 "InnoDB: with raw, and innodb_force_... is removed.\n", 01349 stderr); 01350 01351 return(DB_ERROR); 01352 } 01353 01354 trx->op_info = "updating or deleting"; 01355 01356 row_mysql_delay_if_needed(); 01357 01358 trx_start_if_not_started(trx); 01359 01360 node = prebuilt->upd_node; 01361 01362 clust_index = dict_table_get_first_index(table); 01363 01364 if (prebuilt->pcur->btr_cur.index == clust_index) { 01365 btr_pcur_copy_stored_position(node->pcur, prebuilt->pcur); 01366 } else { 01367 btr_pcur_copy_stored_position(node->pcur, 01368 prebuilt->clust_pcur); 01369 } 01370 01371 ut_a(node->pcur->rel_pos == BTR_PCUR_ON); 01372 01373 /* MySQL seems to call rnd_pos before updating each row it 01374 has cached: we can get the correct cursor position from 01375 prebuilt->pcur; NOTE that we cannot build the row reference 01376 from mysql_rec if the clustered index was automatically 01377 generated for the table: MySQL does not know anything about 01378 the row id used as the clustered index key */ 01379 01380 savept = trx_savept_take(trx); 01381 01382 thr = que_fork_get_first_thr(prebuilt->upd_graph); 01383 01384 node->state = UPD_NODE_UPDATE_CLUSTERED; 01385 01386 ut_ad(!prebuilt->sql_stat_start); 01387 01388 que_thr_move_to_run_state_for_mysql(thr, trx); 01389 01390 run_again: 01391 thr->run_node = node; 01392 thr->prev_node = node; 01393 01394 row_upd_step(thr); 01395 01396 err = trx->error_state; 01397 01398 if (err != DB_SUCCESS) { 01399 que_thr_stop_for_mysql(thr); 01400 01401 if (err == DB_RECORD_NOT_FOUND) { 01402 trx->error_state = DB_SUCCESS; 01403 trx->op_info = ""; 01404 01405 return((int) err); 01406 } 01407 01408 thr->lock_state= QUE_THR_LOCK_ROW; 01409 was_lock_wait = row_mysql_handle_errors(&err, trx, thr, 01410 &savept); 01411 thr->lock_state= QUE_THR_LOCK_NOLOCK; 01412 01413 if (was_lock_wait) { 01414 goto run_again; 01415 } 01416 01417 trx->op_info = ""; 01418 01419 return((int) err); 01420 } 01421 01422 que_thr_stop_for_mysql_no_error(thr, trx); 01423 01424 if (node->is_delete) { 01425 if (prebuilt->table->stat_n_rows > 0) { 01426 prebuilt->table->stat_n_rows--; 01427 } 01428 01429 srv_n_rows_deleted++; 01430 } else { 01431 srv_n_rows_updated++; 01432 } 01433 01434 row_update_statistics_if_needed(prebuilt->table); 01435 01436 trx->op_info = ""; 01437 01438 return((int) err); 01439 }
Here is the call graph for this function:

| void row_update_prebuilt_trx | ( | row_prebuilt_t * | prebuilt, | |
| trx_t * | trx | |||
| ) |
Definition at line 753 of file row0mysql.c.
References row_prebuilt_struct::ins_graph, trx_struct::magic_n, row_prebuilt_struct::magic_n, mem_analyze_corruption(), dict_table_struct::name, NULL, ROW_PREBUILT_ALLOCATED, row_prebuilt_struct::sel_graph, row_prebuilt_struct::table, TRUE, row_prebuilt_struct::trx, que_fork_struct::trx, TRX_MAGIC_N, row_prebuilt_struct::upd_graph, ut_error, and ut_print_name().
00755 : prebuilt dtuple */ 00756 row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL 00757 handle */ 00758 trx_t* trx) /* in: transaction handle */ 00759 { 00760 if (trx->magic_n != TRX_MAGIC_N) { 00761 fprintf(stderr, 00762 "InnoDB: Error: trying to use a corrupt\n" 00763 "InnoDB: trx handle. Magic n %lu\n", 00764 (ulong) trx->magic_n); 00765 00766 mem_analyze_corruption(trx); 00767 00768 ut_error; 00769 } 00770 00771 if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) { 00772 fprintf(stderr, 00773 "InnoDB: Error: trying to use a corrupt\n" 00774 "InnoDB: table handle. Magic n %lu, table name", 00775 (ulong) prebuilt->magic_n); 00776 ut_print_name(stderr, NULL, TRUE, prebuilt->table->name); 00777 putc('\n', stderr); 00778 00779 mem_analyze_corruption(prebuilt); 00780 00781 ut_error; 00782 } 00783 00784 prebuilt->trx = trx; 00785 00786 if (prebuilt->ins_graph) { 00787 prebuilt->ins_graph->trx = trx; 00788 } 00789 00790 if (prebuilt->upd_graph) { 00791 prebuilt->upd_graph->trx = trx; 00792 } 00793 00794 if (prebuilt->sel_graph) { 00795 prebuilt->sel_graph->trx = trx; 00796 } 00797 }
Here is the call graph for this function:

1.4.7

