/***********************************************************//** Undoes a row operation in a table. This is a high-level function used in SQL execution graphs. @return query thread to run next or NULL */ UNIV_INTERN que_thr_t* row_undo_step( /*==========*/ que_thr_t* thr) /*!< in: query thread */ { ulint err; undo_node_t* node; trx_t* trx; ut_ad(thr); srv_activity_count++; trx = thr_get_trx(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_UNDO); err = row_undo(node, thr); trx->error_state = err; if (err != DB_SUCCESS) { /* SQL error detected */ fprintf(stderr, "InnoDB: Fatal error %lu in rollback.\n", (ulong) err); if (err == DB_OUT_OF_FILE_SPACE) { fprintf(stderr, "InnoDB: Error 13 means out of tablespace.\n" "InnoDB: Consider increasing" " your tablespace.\n"); exit(1); } ut_error; return(NULL); } return(thr); }
/***********************************************************//** Does the purge operation for a single undo log record. This is a high-level function used in an SQL execution graph. @return query thread to run next or NULL */ UNIV_INTERN que_thr_t* row_purge_step( /*===========*/ que_thr_t* thr) /*!< in: query thread */ { purge_node_t* node; ut_ad(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); row_purge(node, thr); return(thr); }
/***********************************************************//** Performs an execution step for a commit type node in a query graph. @return query thread to run next, or NULL */ UNIV_INTERN que_thr_t* trx_commit_step( /*============*/ que_thr_t* thr) /*!< in: query thread */ { commit_node_t* node; que_thr_t* next_thr; node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_COMMIT); if (thr->prev_node == que_node_get_parent(node)) { node->state = COMMIT_NODE_SEND; } if (node->state == COMMIT_NODE_SEND) { mutex_enter(&kernel_mutex); node->state = COMMIT_NODE_WAIT; next_thr = NULL; thr->state = QUE_THR_SIG_REPLY_WAIT; /* Send the commit signal to the transaction */ trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT, TRX_SIG_SELF, thr, NULL, &next_thr); mutex_exit(&kernel_mutex); return(next_thr); } ut_ad(node->state == COMMIT_NODE_WAIT); node->state = COMMIT_NODE_SEND; thr->run_node = que_node_get_parent(node); return(thr); }
void row_upd_in_place_in_select( /*=======================*/ sel_node_t* sel_node, /* in: select node */ que_thr_t* thr, /* in: query thread */ mtr_t* mtr) /* in: mtr */ { upd_node_t* node; btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; ut_ad(sel_node->select_will_do_update); ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF); ut_ad(sel_node->asc); node = que_node_get_parent(sel_node); ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE); pcur = node->pcur; btr_cur = btr_pcur_get_btr_cur(pcur); /* Copy the necessary columns from clust_rec and calculate the new values to set */ row_upd_copy_columns(btr_pcur_get_rec(pcur), UT_LIST_GET_FIRST(node->columns)); row_upd_eval_new_vals(node->update); ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur))); ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE); ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE); ut_ad(node->select_will_do_update); err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur, node->update, node->cmpl_info, thr, mtr); ut_ad(err == DB_SUCCESS); }
que_thr_t* row_purge_step( /*===========*/ /* out: query thread to run next or NULL */ que_thr_t* thr) /* in: query thread */ { purge_node_t* node; ulint err; ut_ad(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); err = row_purge(node, thr); ut_ad(err == DB_SUCCESS); return(thr); }
que_thr_t* dict_create_index_step( /*===================*/ /* out: query thread to run next or NULL */ que_thr_t* thr) /* in: query thread */ { ind_node_t* node; ulint err = DB_ERROR; trx_t* trx; ut_ad(thr); ut_ad(mutex_own(&(dict_sys->mutex))); trx = thr_get_trx(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX); if (thr->prev_node == que_node_get_parent(node)) { node->state = INDEX_BUILD_INDEX_DEF; } if (node->state == INDEX_BUILD_INDEX_DEF) { /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ err = dict_build_index_def_step(thr, node); if (err != DB_SUCCESS) { goto function_exit; } node->state = INDEX_BUILD_FIELD_DEF; node->field_no = 0; thr->run_node = node->ind_def; return(thr); } if (node->state == INDEX_BUILD_FIELD_DEF) { if (node->field_no < (node->index)->n_fields) { err = dict_build_field_def_step(node); if (err != DB_SUCCESS) { goto function_exit; } node->field_no++; thr->run_node = node->field_def; return(thr); } else { node->state = INDEX_CREATE_INDEX_TREE; } } if (node->state == INDEX_CREATE_INDEX_TREE) { err = dict_create_index_tree_step(node); if (err != DB_SUCCESS) { goto function_exit; } node->state = INDEX_COMMIT_WORK; } if (node->state == INDEX_COMMIT_WORK) { /* Index was correctly defined: do NOT commit the transaction (CREATE INDEX does NOT currently do an implicit commit of the current transaction) */ node->state = INDEX_ADD_TO_CACHE; /* thr->run_node = node->commit_node; return(thr); */ } if (node->state == INDEX_ADD_TO_CACHE) { dict_index_add_to_cache(node->table, node->index, node->page_no); err = DB_SUCCESS; } function_exit: trx->error_state = err; if (err == DB_SUCCESS) { /* Ok: do nothing */ } else if (err == DB_LOCK_WAIT) { return(NULL); } else { /* SQL error detected */ return(NULL); } thr->run_node = que_node_get_parent(node); return(thr); }
que_thr_t* row_upd_step( /*=========*/ /* out: query thread to run next or NULL */ que_thr_t* thr) /* in: query thread */ { upd_node_t* node; sel_node_t* sel_node; que_node_t* parent; ulint err = DB_SUCCESS; trx_t* trx; ut_ad(thr); trx = thr_get_trx(thr); trx_start_if_not_started(trx); node = thr->run_node; sel_node = node->select; parent = que_node_get_parent(node); ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE); if (thr->prev_node == parent) { node->state = UPD_NODE_SET_IX_LOCK; } if (node->state == UPD_NODE_SET_IX_LOCK) { if (!node->has_clust_rec_x_lock) { /* It may be that the current session has not yet started its transaction, or it has been committed: */ err = lock_table(0, node->table, LOCK_IX, thr); if (err != DB_SUCCESS) { goto error_handling; } } node->state = UPD_NODE_UPDATE_CLUSTERED; if (node->searched_update) { /* Reset the cursor */ sel_node->state = SEL_NODE_OPEN; /* Fetch a row to update */ thr->run_node = sel_node; return(thr); } } /* sel_node is NULL if we are in the MySQL interface */ if (sel_node && (sel_node->state != SEL_NODE_FETCH)) { if (!node->searched_update) { /* An explicit cursor should be positioned on a row to update */ ut_error; err = DB_ERROR; goto error_handling; } ut_ad(sel_node->state == SEL_NODE_NO_MORE_ROWS); /* No more rows to update, or the select node performed the updates directly in-place */ thr->run_node = parent; return(thr); } /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ err = row_upd(node, thr); error_handling: trx->error_state = err; if (err == DB_SUCCESS) { /* Ok: do nothing */ } else if (err == DB_LOCK_WAIT) { return(NULL); } else { return(NULL); } /* DO THE TRIGGER ACTIONS HERE */ if (node->searched_update) { /* Fetch next row to update */ thr->run_node = sel_node; } else { /* It was an explicit cursor update */ thr->run_node = parent; } node->state = UPD_NODE_UPDATE_CLUSTERED; return(thr); }
/***********************************************************//** Creates a table. This is a high-level function used in SQL execution graphs. @return query thread to run next or NULL */ UNIV_INTERN que_thr_t* dict_create_table_step( /*===================*/ que_thr_t* thr) /*!< in: query thread */ { tab_node_t* node; ulint err = DB_ERROR; trx_t* trx; ut_ad(thr); ut_ad(mutex_own(&(dict_sys->mutex))); trx = thr_get_trx(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_TABLE); if (thr->prev_node == que_node_get_parent(node)) { node->state = TABLE_BUILD_TABLE_DEF; } if (node->state == TABLE_BUILD_TABLE_DEF) { /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ err = dict_build_table_def_step(thr, node); if (err != DB_SUCCESS) { goto function_exit; } node->state = TABLE_BUILD_COL_DEF; node->col_no = 0; thr->run_node = node->tab_def; return(thr); } if (node->state == TABLE_BUILD_COL_DEF) { if (node->col_no < (node->table)->n_def) { err = dict_build_col_def_step(node); if (err != DB_SUCCESS) { goto function_exit; } node->col_no++; thr->run_node = node->col_def; return(thr); } else { node->state = TABLE_COMMIT_WORK; } } if (node->state == TABLE_COMMIT_WORK) { /* Table was correctly defined: do NOT commit the transaction (CREATE TABLE does NOT do an implicit commit of the current transaction) */ node->state = TABLE_ADD_TO_CACHE; /* thr->run_node = node->commit_node; return(thr); */ } if (node->state == TABLE_ADD_TO_CACHE) { dict_table_add_to_cache(node->table, node->heap); err = DB_SUCCESS; } function_exit: trx->error_state = err; if (err == DB_SUCCESS) { /* Ok: do nothing */ } else if (err == DB_LOCK_WAIT) { return(NULL); } else { /* SQL error detected */ return(NULL); } thr->run_node = que_node_get_parent(node); return(thr); }
/***********************************************************//** Creates an index. This is a high-level function used in SQL execution graphs. @return query thread to run next or NULL */ UNIV_INTERN que_thr_t* dict_create_index_step( /*===================*/ que_thr_t* thr) /*!< in: query thread */ { ind_node_t* node; ulint err = DB_ERROR; trx_t* trx; ut_ad(thr); ut_ad(mutex_own(&(dict_sys->mutex))); trx = thr_get_trx(thr); node = thr->run_node; ut_ad(que_node_get_type(node) == QUE_NODE_CREATE_INDEX); if (thr->prev_node == que_node_get_parent(node)) { node->state = INDEX_BUILD_INDEX_DEF; } if (node->state == INDEX_BUILD_INDEX_DEF) { /* DO THE CHECKS OF THE CONSISTENCY CONSTRAINTS HERE */ err = dict_build_index_def_step(thr, node); if (err != DB_SUCCESS) { goto function_exit; } node->state = INDEX_BUILD_FIELD_DEF; node->field_no = 0; thr->run_node = node->ind_def; return(thr); } if (node->state == INDEX_BUILD_FIELD_DEF) { if (node->field_no < (node->index)->n_fields) { err = dict_build_field_def_step(node); if (err != DB_SUCCESS) { goto function_exit; } node->field_no++; thr->run_node = node->field_def; return(thr); } else { node->state = INDEX_ADD_TO_CACHE; } } if (node->state == INDEX_ADD_TO_CACHE) { index_id_t index_id = node->index->id; // err = dict_index_add_to_cache( // node->table, node->index, FIL_NULL, // trx_is_strict(trx) // || dict_table_get_format(node->table) // >= DICT_TF_FORMAT_ZIP); //z- //因为trx_is_strict!/为什么ha_innodb__.cc中的stub无效呢?;----2011-09-20-10-02; err=DB_SUCCESS; //z+ //zlq //----2011-10-12-21-05--21-07; node->index = dict_index_get_if_in_cache_low(index_id); // ut_a(!node->index == (err != DB_SUCCESS)); //z- //zlqlxm //2011-10-13 if (err != DB_SUCCESS) { goto function_exit; } node->state = INDEX_CREATE_INDEX_TREE; } if (node->state == INDEX_CREATE_INDEX_TREE) { err = dict_create_index_tree_step(node); if (err != DB_SUCCESS) { dict_index_remove_from_cache(node->table, node->index); node->index = NULL; goto function_exit; } node->index->page = node->page_no; node->state = INDEX_COMMIT_WORK; } if (node->state == INDEX_COMMIT_WORK) { /* Index was correctly defined: do NOT commit the transaction (CREATE INDEX does NOT currently do an implicit commit of the current transaction) */ node->state = INDEX_CREATE_INDEX_TREE; /* thr->run_node = node->commit_node; return(thr); */ } function_exit: trx->error_state = err; if (err == DB_SUCCESS) { /* Ok: do nothing */ } else if (err == DB_LOCK_WAIT) { return(NULL); } else { /* SQL error detected */ return(NULL); } thr->run_node = que_node_get_parent(node); return(thr); }