diff options
Diffstat (limited to 'storage/innobase/row/row0mysql.cc')
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 776 |
1 files changed, 35 insertions, 741 deletions
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 4a063c9af83..5b38b7c6c01 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1015,9 +1015,6 @@ row_create_prebuilt( prebuilt->mysql_row_len = mysql_row_len; - prebuilt->ins_sel_stmt = false; - prebuilt->session = NULL; - prebuilt->fts_doc_id_in_read_set = 0; prebuilt->blob_heap = NULL; @@ -1407,282 +1404,12 @@ run_again: return(err); } -/** Perform explicit rollback in absence of UNDO logs. -@param[in] index apply rollback action on this index -@param[in] entry entry to remove/rollback. -@param[in,out] thr thread handler. -@param[in,out] mtr mini transaction. -@return error code or DB_SUCCESS */ -static -dberr_t -row_explicit_rollback( - dict_index_t* index, - const dtuple_t* entry, - que_thr_t* thr, - mtr_t* mtr) -{ - btr_cur_t cursor; - ulint flags; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets; - mem_heap_t* heap = NULL; - dberr_t err = DB_SUCCESS; - - rec_offs_init(offsets_); - flags = BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG; - - err = btr_cur_search_to_nth_level_with_no_latch( - index, 0, entry, PAGE_CUR_LE, - &cursor, __FILE__, __LINE__, mtr); - - offsets = rec_get_offsets( - btr_cur_get_rec(&cursor), index, offsets_, - ULINT_UNDEFINED, &heap); - - if (dict_index_is_clust(index)) { - err = btr_cur_del_mark_set_clust_rec( - flags, btr_cur_get_block(&cursor), - btr_cur_get_rec(&cursor), index, - offsets, thr, entry, mtr); - } else { - err = btr_cur_del_mark_set_sec_rec( - flags, &cursor, TRUE, thr, mtr); - } - ut_ad(err == DB_SUCCESS); - - /* Void call just to set mtr modification flag - to true failing which block is not scheduled for flush*/ - byte* log_ptr = mlog_open(mtr, 0); - ut_ad(log_ptr == NULL); - if (log_ptr != NULL) { - /* To keep complier happy. */ - mlog_close(mtr, log_ptr); - } - - if (heap != NULL) { - mem_heap_free(heap); - } - - return(err); -} - -/** Convert a row in the MySQL format to a row in the Innobase format. -This is specialized function used for intrinsic table with reduce branching. -@param[in,out] row row where field values are copied. -@param[in] prebuilt prebuilt handler -@param[in] mysql_rec row in mysql format. */ -static -void -row_mysql_to_innobase( - dtuple_t* row, - row_prebuilt_t* prebuilt, - const byte* mysql_rec) -{ - ut_ad(dict_table_is_intrinsic(prebuilt->table)); - - const byte* ptr = mysql_rec; - - for (ulint i = 0; i < prebuilt->n_template; i++) { - const mysql_row_templ_t* templ; - dfield_t* dfield; - - templ = prebuilt->mysql_template + i; - dfield = dtuple_get_nth_field(row, i); - - /* Check if column has null value. */ - if (templ->mysql_null_bit_mask != 0) { - if (mysql_rec[templ->mysql_null_byte_offset] - & (byte) (templ->mysql_null_bit_mask)) { - dfield_set_null(dfield); - continue; - } - } - - /* Extract the column value. */ - ptr = mysql_rec + templ->mysql_col_offset; - const dtype_t* dtype = dfield_get_type(dfield); - ulint col_len = templ->mysql_col_len; - - ut_ad(dtype->mtype == DATA_INT - || dtype->mtype == DATA_CHAR - || dtype->mtype == DATA_MYSQL - || dtype->mtype == DATA_VARCHAR - || dtype->mtype == DATA_VARMYSQL - || dtype->mtype == DATA_BINARY - || dtype->mtype == DATA_FIXBINARY - || dtype->mtype == DATA_FLOAT - || dtype->mtype == DATA_DOUBLE - || dtype->mtype == DATA_DECIMAL - || dtype->mtype == DATA_BLOB - || dtype->mtype == DATA_GEOMETRY - || dtype->mtype == DATA_POINT - || dtype->mtype == DATA_VAR_POINT); - -#ifdef UNIV_DEBUG - if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) { - ut_ad(templ->mysql_length_bytes > 0); - } -#endif /* UNIV_DEBUG */ - - /* For now varchar field this has to be always 0 so - memcpy of 0 bytes shouldn't affect the original col_len. */ - if (dtype->mtype == DATA_INT) { - /* Convert and Store in big-endian. */ - byte* buf = prebuilt->ins_upd_rec_buff - + templ->mysql_col_offset; - byte* copy_to = buf + col_len; - for (;;) { - copy_to--; - *copy_to = *ptr; - if (copy_to == buf) { - break; - } - ptr++; - } - - if (!(dtype->prtype & DATA_UNSIGNED)) { - *buf ^= 128; - } - - ptr = buf; - buf += col_len; - } else if (dtype_get_mysql_type(dtype) == - DATA_MYSQL_TRUE_VARCHAR) { - - ut_ad(dtype->mtype == DATA_VARCHAR - || dtype->mtype == DATA_VARMYSQL - || dtype->mtype == DATA_BINARY); - - col_len = 0; - row_mysql_read_true_varchar( - &col_len, ptr, templ->mysql_length_bytes); - ptr += templ->mysql_length_bytes; - } else if (dtype->mtype == DATA_BLOB) { - ptr = row_mysql_read_blob_ref(&col_len, ptr, col_len); - } else if (DATA_GEOMETRY_MTYPE(dtype->mtype)) { - /* Point, Var-Point, Geometry */ - ptr = row_mysql_read_geometry(&col_len, ptr, col_len); - } - - dfield_set_data(dfield, ptr, col_len); - } -} - -/** Does an insert for MySQL using cursor interface. -Cursor interface is low level interface that directly interacts at -Storage Level by-passing all the locking and transaction semantics. -For InnoDB case, this will also by-pass hidden column generation. -@param[in] mysql_rec row in the MySQL format -@param[in,out] prebuilt prebuilt struct in MySQL handle -@return error code or DB_SUCCESS */ -static -dberr_t -row_insert_for_mysql_using_cursor( - const byte* mysql_rec, - row_prebuilt_t* prebuilt) -{ - dberr_t err = DB_SUCCESS; - ins_node_t* node = NULL; - que_thr_t* thr = NULL; - mtr_t mtr; - - /* Step-1: Get the reference of row to insert. */ - row_get_prebuilt_insert_row(prebuilt); - node = prebuilt->ins_node; - thr = que_fork_get_first_thr(prebuilt->ins_graph); - - /* Step-2: Convert row from MySQL row format to InnoDB row format. */ - row_mysql_to_innobase(node->row, prebuilt, mysql_rec); - - /* Step-3: Append row-id index is not unique. */ - dict_index_t* clust_index = dict_table_get_first_index(node->table); - - if (!dict_index_is_unique(clust_index)) { - dict_sys_write_row_id( - node->row_id_buf, - dict_table_get_next_table_sess_row_id(node->table)); - } - - trx_write_trx_id(node->trx_id_buf, - dict_table_get_next_table_sess_trx_id(node->table)); - - /* Step-4: Iterate over all the indexes and insert entries. */ - dict_index_t* inserted_upto = NULL; - node->entry = UT_LIST_GET_FIRST(node->entry_list); - for (dict_index_t* index = UT_LIST_GET_FIRST(node->table->indexes); - index != NULL; - index = UT_LIST_GET_NEXT(indexes, index), - node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry)) { - - node->index = index; - err = row_ins_index_entry_set_vals( - node->index, node->entry, node->row); - if (err != DB_SUCCESS) { - break; - } - - if (dict_index_is_clust(index)) { - err = row_ins_clust_index_entry( - node->index, node->entry, thr, 0, false); - } else { - err = row_ins_sec_index_entry( - node->index, node->entry, thr, false); - } - - if (err == DB_SUCCESS) { - inserted_upto = index; - } else { - break; - } - } - - /* Step-5: If error is encountered while inserting entries to any - of the index then entries inserted to previous indexes are removed - explicity. Automatic rollback is not in action as UNDO logs are - turned-off. */ - if (err != DB_SUCCESS) { - - node->entry = UT_LIST_GET_FIRST(node->entry_list); - - mtr_start(&mtr); - dict_disable_redo_if_temporary(node->table, &mtr); - - for (dict_index_t* index = - UT_LIST_GET_FIRST(node->table->indexes); - inserted_upto != NULL; - index = UT_LIST_GET_NEXT(indexes, index), - node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry)) { - - row_explicit_rollback(index, node->entry, thr, &mtr); - - if (index == inserted_upto) { - break; - } - } - - mtr_commit(&mtr); - } else { - /* Not protected by dict_table_stats_lock() for performance - reasons, we would rather get garbage in stat_n_rows (which is - just an estimate anyway) than protecting the following code - , with a latch. */ - dict_table_n_rows_inc(node->table); - - srv_stats.n_rows_inserted.inc(); - } - - thr_get_trx(thr)->error_state = DB_SUCCESS; - return(err); -} - -/** Does an insert for MySQL using INSERT graph. This function will run/execute -INSERT graph. +/** Does an insert for MySQL. @param[in] mysql_rec row in the MySQL format @param[in,out] prebuilt prebuilt struct in MySQL handle @return error code or DB_SUCCESS */ -static dberr_t -row_insert_for_mysql_using_ins_graph( +row_insert_for_mysql( const byte* mysql_rec, row_prebuilt_t* prebuilt) { @@ -1896,26 +1623,6 @@ error_exit: return(err); } -/** Does an insert for MySQL. -@param[in] mysql_rec row in the MySQL format -@param[in,out] prebuilt prebuilt struct in MySQL handle -@return error code or DB_SUCCESS*/ -dberr_t -row_insert_for_mysql( - const byte* mysql_rec, - row_prebuilt_t* prebuilt) -{ - /* For intrinsic tables there a lot of restrictions that can be - relaxed including locking of table, transaction handling, etc. - Use direct cursor interface for inserting to intrinsic tables. */ - if (dict_table_is_intrinsic(prebuilt->table)) { - return(row_insert_for_mysql_using_cursor(mysql_rec, prebuilt)); - } else { - return(row_insert_for_mysql_using_ins_graph( - mysql_rec, prebuilt)); - } -} - /*********************************************************************//** Builds a dummy query graph used in selects. */ void @@ -2129,314 +1836,6 @@ public: }; -typedef std::vector<btr_pcur_t, ut_allocator<btr_pcur_t> > cursors_t; - -/** Delete row from table (corresponding entries from all the indexes). -Function will maintain cursor to the entries to invoke explicity rollback -just incase update action following delete fails. - -@param[in] node update node carrying information to delete. -@param[out] delete_entries vector of cursor to deleted entries. -@param[in] restore_delete if true, then restore DELETE records by - unmarking delete. -@return error code or DB_SUCCESS */ -static -dberr_t -row_delete_for_mysql_using_cursor( - const upd_node_t* node, - cursors_t& delete_entries, - bool restore_delete) -{ - mtr_t mtr; - dict_table_t* table = node->table; - mem_heap_t* heap = mem_heap_create(1000); - dberr_t err = DB_SUCCESS; - dtuple_t* entry; - - mtr_start(&mtr); - dict_disable_redo_if_temporary(table, &mtr); - - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != NULL && err == DB_SUCCESS && !restore_delete; - index = UT_LIST_GET_NEXT(indexes, index)) { - - entry = row_build_index_entry( - node->row, node->ext, index, heap); - - btr_pcur_t pcur; - - btr_pcur_open(index, entry, PAGE_CUR_LE, - BTR_MODIFY_LEAF, &pcur, &mtr); - -#ifdef UNIV_DEBUG - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets = offsets_; - rec_offs_init(offsets_); - - offsets = rec_get_offsets( - btr_cur_get_rec(btr_pcur_get_btr_cur(&pcur)), - index, offsets, ULINT_UNDEFINED, &heap); - - ut_ad(!cmp_dtuple_rec( - entry, btr_cur_get_rec(btr_pcur_get_btr_cur(&pcur)), - offsets)); -#endif /* UNIV_DEBUG */ - - ut_ad(!rec_get_deleted_flag( - btr_cur_get_rec(btr_pcur_get_btr_cur(&pcur)), - dict_table_is_comp(index->table))); - - ut_ad(btr_pcur_get_block(&pcur)->made_dirty_with_no_latch); - - if (page_rec_is_infimum(btr_pcur_get_rec(&pcur)) - || page_rec_is_supremum(btr_pcur_get_rec(&pcur))) { - err = DB_ERROR; - } else { - btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur); - - btr_rec_set_deleted_flag( - btr_cur_get_rec(btr_cur), - buf_block_get_page_zip( - btr_cur_get_block(btr_cur)), - TRUE); - - /* Void call just to set mtr modification flag - to true failing which block is not scheduled for flush*/ - byte* log_ptr = mlog_open(&mtr, 0); - ut_ad(log_ptr == NULL); - if (log_ptr != NULL) { - /* To keep complier happy. */ - mlog_close(&mtr, log_ptr); - } - - btr_pcur_store_position(&pcur, &mtr); - - delete_entries.push_back(pcur); - } - } - - if (err != DB_SUCCESS || restore_delete) { - - /* Rollback half-way delete action that might have been - applied to few of the indexes. */ - cursors_t::iterator end = delete_entries.end(); - for (cursors_t::iterator it = delete_entries.begin(); - it != end; - ++it) { - - ibool success = btr_pcur_restore_position( - BTR_MODIFY_LEAF, &(*it), &mtr); - - if (!success) { - ut_a(success); - } else { - btr_cur_t* btr_cur = btr_pcur_get_btr_cur( - &(*it)); - - ut_ad(btr_cur_get_block( - btr_cur)->made_dirty_with_no_latch); - - btr_rec_set_deleted_flag( - btr_cur_get_rec(btr_cur), - buf_block_get_page_zip( - btr_cur_get_block(btr_cur)), - FALSE); - - /* Void call just to set mtr modification flag - to true failing which block is not scheduled for - flush. */ - byte* log_ptr = mlog_open(&mtr, 0); - ut_ad(log_ptr == NULL); - if (log_ptr != NULL) { - /* To keep complier happy. */ - mlog_close(&mtr, log_ptr); - } - } - } - } - - mtr_commit(&mtr); - - mem_heap_free(heap); - - return(err); -} - -/** Does an update of a row for MySQL by inserting new entry with update values. -@param[in] node update node carrying information to delete. -@param[out] delete_entries vector of cursor to deleted entries. -@param[in] thr thread handler -@return error code or DB_SUCCESS */ -static -dberr_t -row_update_for_mysql_using_cursor( - const upd_node_t* node, - cursors_t& delete_entries, - que_thr_t* thr) -{ - dberr_t err = DB_SUCCESS; - dict_table_t* table = node->table; - mem_heap_t* heap = mem_heap_create(1000); - dtuple_t* entry; - dfield_t* trx_id_field; - - /* Step-1: Update row-id column if table doesn't have unique index. */ - if (!dict_index_is_unique(dict_table_get_first_index(table))) { - /* Update the row_id column. */ - dfield_t* row_id_field; - - row_id_field = dtuple_get_nth_field( - node->upd_row, dict_table_get_n_cols(table) - 2); - - dict_sys_write_row_id( - static_cast<byte*>(row_id_field->data), - dict_table_get_next_table_sess_row_id(node->table)); - } - - /* Step-2: Update the trx_id column. */ - trx_id_field = dtuple_get_nth_field( - node->upd_row, dict_table_get_n_cols(table) - 1); - trx_write_trx_id(static_cast<byte*>(trx_id_field->data), - dict_table_get_next_table_sess_trx_id(node->table)); - - - /* Step-3: Check if UPDATE can lead to DUPLICATE key violation. - If yes, then avoid executing it and return error. Only after ensuring - that UPDATE is safe execute it as we can't rollback. */ - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != NULL && err == DB_SUCCESS; - index = UT_LIST_GET_NEXT(indexes, index)) { - - entry = row_build_index_entry( - node->upd_row, node->upd_ext, index, heap); - - if (dict_index_is_clust(index)) { - if (!dict_index_is_auto_gen_clust(index)) { - err = row_ins_clust_index_entry( - index, entry, thr, - node->upd_ext - ? node->upd_ext->n_ext : 0, - true); - } - } else { - err = row_ins_sec_index_entry(index, entry, thr, true); - } - } - - if (err != DB_SUCCESS) { - /* This suggest update can't be executed safely. - Avoid executing update. Rollback DELETE action. */ - row_delete_for_mysql_using_cursor(node, delete_entries, true); - } - - /* Step-4: It is now safe to execute update if there is no error */ - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != NULL && err == DB_SUCCESS; - index = UT_LIST_GET_NEXT(indexes, index)) { - - entry = row_build_index_entry( - node->upd_row, node->upd_ext, index, heap); - - if (dict_index_is_clust(index)) { - err = row_ins_clust_index_entry( - index, entry, thr, - node->upd_ext ? node->upd_ext->n_ext : 0, - false); - /* Commit the open mtr as we are processing UPDATE. */ - index->last_ins_cur->release(); - } else { - err = row_ins_sec_index_entry(index, entry, thr, false); - } - - /* Too big record is valid error and suggestion is to use - bigger page-size or different format. */ - ut_ad(err == DB_SUCCESS - || err == DB_TOO_BIG_RECORD - || err == DB_OUT_OF_FILE_SPACE); - - if (err == DB_TOO_BIG_RECORD) { - row_delete_for_mysql_using_cursor( - node, delete_entries, true); - } - } - - if (heap != NULL) { - mem_heap_free(heap); - } - return(err); -} - -/** Does an update or delete of a row for MySQL. -@param[in] mysql_rec row in the MySQL format -@param[in,out] prebuilt prebuilt struct in MySQL handle -@return error code or DB_SUCCESS */ -static -dberr_t -row_del_upd_for_mysql_using_cursor( - const byte* mysql_rec, - row_prebuilt_t* prebuilt) -{ - dberr_t err = DB_SUCCESS; - upd_node_t* node; - cursors_t delete_entries; - dict_index_t* clust_index; - que_thr_t* thr = NULL; - - /* Step-0: If there is cached insert position commit it before - starting delete/update action as this can result in btree structure - to change. */ - thr = que_fork_get_first_thr(prebuilt->upd_graph); - clust_index = dict_table_get_first_index(prebuilt->table); - clust_index->last_ins_cur->release(); - - /* Step-1: Select the appropriate cursor that will help build - the original row and updated row. */ - node = prebuilt->upd_node; - if (prebuilt->pcur->btr_cur.index == clust_index) { - btr_pcur_copy_stored_position(node->pcur, prebuilt->pcur); - } else { - btr_pcur_copy_stored_position(node->pcur, - prebuilt->clust_pcur); - } - - ut_ad(dict_table_is_intrinsic(prebuilt->table)); - ut_ad(!prebuilt->table->n_v_cols); - - /* Internal table is created by optimiser. So there - should not be any virtual columns. */ - row_upd_store_row(node, NULL, NULL); - - /* Step-2: Execute DELETE operation. */ - err = row_delete_for_mysql_using_cursor(node, delete_entries, false); - - /* Step-3: If only DELETE operation then exit immediately. */ - if (node->is_delete) { - if (err == DB_SUCCESS) { - dict_table_n_rows_dec(prebuilt->table); - srv_stats.n_rows_deleted.inc(); - } - } - - if (err == DB_SUCCESS && !node->is_delete) { - /* Step-4: Complete UPDATE operation by inserting new row with - updated data. */ - err = row_update_for_mysql_using_cursor( - node, delete_entries, thr); - - if (err == DB_SUCCESS) { - srv_stats.n_rows_updated.inc(); - } - } - - thr_get_trx(thr)->error_state = DB_SUCCESS; - cursors_t::iterator end = delete_entries.end(); - for (cursors_t::iterator it = delete_entries.begin(); it != end; ++it) { - btr_pcur_close(&(*it)); - } - - return(err); -} - /** Does an update or delete of a row for MySQL. @param[in] mysql_rec row in the MySQL format @param[in,out] prebuilt prebuilt struct in MySQL handle @@ -2794,41 +2193,8 @@ row_update_for_mysql( const byte* mysql_rec, row_prebuilt_t* prebuilt) { - if (dict_table_is_intrinsic(prebuilt->table)) { - return(row_del_upd_for_mysql_using_cursor(mysql_rec, prebuilt)); - } else { - ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); - return(row_update_for_mysql_using_upd_graph( - mysql_rec, prebuilt)); - } -} - -/** Delete all rows for the given table by freeing/truncating indexes. -@param[in,out] table table handler -@return error code or DB_SUCCESS */ -dberr_t -row_delete_all_rows( - dict_table_t* table) -{ - dberr_t err = DB_SUCCESS; - - /* Step-0: If there is cached insert position along with mtr - commit it before starting delete/update action. */ - dict_table_get_first_index(table)->last_ins_cur->release(); - - /* Step-1: Now truncate all the indexes and re-create them. - Note: This is ddl action even though delete all rows is - DML action. Any error during this action is ir-reversible. */ - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != NULL && err == DB_SUCCESS; - index = UT_LIST_GET_NEXT(indexes, index)) { - - err = dict_truncate_index_tree_in_mem(index); - // TODO: what happen if get an error - ut_ad(err == DB_SUCCESS); - } - - return(err); + ut_a(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); + return(row_update_for_mysql_using_upd_graph(mysql_rec, prebuilt)); } /** This can only be used when srv_locks_unsafe_for_binlog is TRUE or this @@ -3258,13 +2624,12 @@ row_create_index_for_mysql( dict_index_t* index, /*!< in, own: index definition (will be freed) */ trx_t* trx, /*!< in: transaction handle */ - const ulint* field_lengths, /*!< in: if not NULL, must contain + const ulint* field_lengths) /*!< in: if not NULL, must contain dict_index_get_n_fields(index) actual field lengths for the index columns, which are then checked for not being too large. */ - dict_table_t* handler) /*!< in/out: table handler. */ { ind_node_t* node; mem_heap_t* heap; @@ -3287,22 +2652,11 @@ row_create_index_for_mysql( is_fts = (index->type == DICT_FTS); - if (handler != NULL && dict_table_is_intrinsic(handler)) { - table = handler; - } - - if (table == NULL) { - - ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); - ut_ad(mutex_own(&dict_sys->mutex)); - - table = dict_table_open_on_name(table_name, TRUE, TRUE, - DICT_ERR_IGNORE_NONE); + ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); + ut_ad(mutex_own(&dict_sys->mutex)); - } else { - table->acquire(); - ut_ad(dict_table_is_intrinsic(table)); - } + table = dict_table_open_on_name(table_name, TRUE, TRUE, + DICT_ERR_IGNORE_NONE); if (!dict_table_is_temporary(table)) { trx_start_if_not_started_xa(trx, true); @@ -3361,13 +2715,9 @@ row_create_index_for_mysql( index_id_t index_id = index->id; - /* add index to dictionary cache and also free index object. - We allow instrinsic table to violate the size limits because - they are used by optimizer for all record formats. */ + /* add index to dictionary cache and also free index object. */ err = dict_index_add_to_cache( - table, index, FIL_NULL, - !dict_table_is_intrinsic(table) - && trx_is_strict(trx)); + table, index, FIL_NULL, trx_is_strict(trx)); if (err != DB_SUCCESS) { goto error_handling; @@ -3375,23 +2725,13 @@ row_create_index_for_mysql( /* as above function has freed index object re-load it now from dictionary cache using index_id */ - if (!dict_table_is_intrinsic(table)) { - index = dict_index_get_if_in_cache_low(index_id); - } else { - index = dict_table_find_index_on_id(table, index_id); - - /* trx_id field is used for tracking which transaction - created the index. For intrinsic table this is - ir-relevant and so re-use it for tracking consistent - view while processing SELECT as part of UPDATE. */ - index->trx_id = ULINT_UNDEFINED; - } + index = dict_index_get_if_in_cache_low(index_id); ut_a(index != NULL); index->table = table; err = dict_create_index_tree_in_mem(index, trx); - if (err != DB_SUCCESS && !dict_table_is_intrinsic(table)) { + if (err != DB_SUCCESS) { dict_index_remove_from_cache(table, index); } } @@ -3420,7 +2760,7 @@ error_handling: trx_rollback_to_savepoint(trx, NULL); } - row_drop_table_for_mysql(table_name, trx, FALSE, true, handler); + row_drop_table_for_mysql(table_name, trx, FALSE, true); if (trx_is_started(trx)) { @@ -3489,9 +2829,6 @@ row_table_add_foreign_constraints( DEBUG_SYNC_C("table_add_foreign_constraints"); - /* Check like this shouldn't be done for table that doesn't - have foreign keys but code still continues to run with void action. - Disable it for intrinsic table at-least */ if (err == DB_SUCCESS) { /* Check that also referencing constraints are ok */ dict_names_t fk_tables; @@ -4263,23 +3600,7 @@ row_drop_table_from_cache( is going to be destroyed below. */ trx->mod_tables.erase(table); - if (!dict_table_is_intrinsic(table)) { - dict_table_remove_from_cache(table); - } else { - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != NULL; - index = UT_LIST_GET_FIRST(table->indexes)) { - - rw_lock_free(&index->lock); - - UT_LIST_REMOVE(table->indexes, index); - - dict_mem_index_free(index); - } - - dict_mem_table_free(table); - table = NULL; - } + dict_table_remove_from_cache(table); if (!is_temp && dict_load_table(tablename, true, @@ -4355,7 +3676,6 @@ will remain locked. because e.g. foreign key column @param[in] nonatomic Whether it is permitted to release and reacquire dict_operation_lock -@param[in,out] handler Table handler @return error code or DB_SUCCESS */ dberr_t row_drop_table_for_mysql( @@ -4363,18 +3683,16 @@ row_drop_table_for_mysql( trx_t* trx, bool drop_db, ibool create_failed, - bool nonatomic, - dict_table_t* handler) + bool nonatomic) { dberr_t err; dict_foreign_t* foreign; - dict_table_t* table = NULL; + dict_table_t* table; char* filepath = NULL; char* tablename = NULL; bool locked_dictionary = false; pars_info_t* info = NULL; mem_heap_t* heap = NULL; - bool is_intrinsic_temp_table = false; DBUG_ENTER("row_drop_table_for_mysql"); DBUG_PRINT("row_drop_table_for_mysql", ("table: '%s'", name)); @@ -4386,35 +3704,24 @@ row_drop_table_for_mysql( trx->op_info = "dropping table"; - if (handler != NULL && dict_table_is_intrinsic(handler)) { - table = handler; - is_intrinsic_temp_table = true; - } - - if (table == NULL) { - - if (trx->dict_operation_lock_mode != RW_X_LATCH) { - /* Prevent foreign key checks etc. while we are - dropping the table */ + if (trx->dict_operation_lock_mode != RW_X_LATCH) { + /* Prevent foreign key checks etc. while we are + dropping the table */ - row_mysql_lock_data_dictionary(trx); + row_mysql_lock_data_dictionary(trx); - locked_dictionary = true; - nonatomic = true; - } + locked_dictionary = true; + nonatomic = true; + } - ut_ad(mutex_own(&dict_sys->mutex)); - ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); - table = dict_table_open_on_name( - name, TRUE, FALSE, - static_cast<dict_err_ignore_t>( - DICT_ERR_IGNORE_INDEX_ROOT - | DICT_ERR_IGNORE_CORRUPT)); - } else { - table->acquire(); - ut_ad(dict_table_is_intrinsic(table)); - } + table = dict_table_open_on_name( + name, TRUE, FALSE, + static_cast<dict_err_ignore_t>( + DICT_ERR_IGNORE_INDEX_ROOT + | DICT_ERR_IGNORE_CORRUPT)); if (!table) { err = DB_TABLE_NOT_FOUND; @@ -4495,10 +3802,7 @@ row_drop_table_for_mysql( } } - if (!dict_table_is_intrinsic(table)) { - dict_table_prevent_eviction(table); - } - + dict_table_prevent_eviction(table); dict_table_close(table, TRUE, FALSE); /* Check if the table is referenced by foreign key constraints from @@ -4600,16 +3904,11 @@ row_drop_table_for_mysql( fil_wait_crypt_bg_threads(table); if (table->get_ref_count() == 0) { - /* We don't take lock on intrinsic table so nothing to remove.*/ - if (!dict_table_is_intrinsic(table)) { - lock_remove_all_on_table(table, TRUE); - } + lock_remove_all_on_table(table, TRUE); ut_a(table->n_rec_locks == 0); } else if (table->get_ref_count() > 0 || table->n_rec_locks > 0) { ibool added; - ut_ad(!dict_table_is_intrinsic(table)); - added = row_add_table_to_background_drop_list( table->name.m_name); @@ -4641,7 +3940,7 @@ row_drop_table_for_mysql( /* If we get this far then the table to be dropped must not have any table or record locks on it. */ - ut_a(dict_table_is_intrinsic(table) || !lock_table_has_locks(table)); + ut_a(!lock_table_has_locks(table)); switch (trx_get_dict_operation(trx)) { case TRX_DICT_OP_NONE: @@ -4974,12 +4273,7 @@ funct_exit: trx->op_info = ""; - /* No need to immediately invoke master thread as there is no work - generated by intrinsic table operation that needs master thread - attention. */ - if (!is_intrinsic_temp_table) { - srv_wake_master_thread(); - } + srv_wake_master_thread(); DBUG_RETURN(err); } |