diff options
Diffstat (limited to 'storage/xtradb/row/row0sel.c')
-rw-r--r-- | storage/xtradb/row/row0sel.c | 523 |
1 files changed, 258 insertions, 265 deletions
diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index fb1523d3370..3ef9726588e 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -23,7 +23,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ -/******************************************************* +/***************************************************//** +@file row/row0sel.c Select Created 12/19/1997 Heikki Tuuri @@ -74,34 +75,33 @@ to que_run_threads: this is to allow canceling runaway queries */ #define SEL_EXHAUSTED 1 #define SEL_RETRY 2 -/************************************************************************ +/********************************************************************//** Returns TRUE if the user-defined column in a secondary index record is alphabetically the same as the corresponding BLOB column in the clustered index record. NOTE: the comparison is NOT done as a binary comparison, but character -fields are compared with collation! */ +fields are compared with collation! +@return TRUE if the columns are equal */ static ibool row_sel_sec_rec_is_for_blob( /*========================*/ - /* out: TRUE if the columns - are equal */ - ulint mtype, /* in: main type */ - ulint prtype, /* in: precise type */ - ulint mbminlen, /* in: minimum length of a + ulint mtype, /*!< in: main type */ + ulint prtype, /*!< in: precise type */ + ulint mbminlen, /*!< in: minimum length of a multi-byte character */ - ulint mbmaxlen, /* in: maximum length of a + ulint mbmaxlen, /*!< in: maximum length of a multi-byte character */ - const byte* clust_field, /* in: the locally stored part of + const byte* clust_field, /*!< in: the locally stored part of the clustered index column, including the BLOB pointer; the clustered index record must be covered by a lock or a page latch to protect it against deletion (rollback or purge) */ - ulint clust_len, /* in: length of clust_field */ - const byte* sec_field, /* in: column in secondary index */ - ulint sec_len, /* in: length of sec_field */ - ulint zip_size) /* in: compressed page size, or 0 */ + ulint clust_len, /*!< in: length of clust_field */ + const byte* sec_field, /*!< in: column in secondary index */ + ulint sec_len, /*!< in: length of sec_field */ + ulint zip_size) /*!< in: compressed page size, or 0 */ { ulint len; byte buf[DICT_MAX_INDEX_COL_LEN]; @@ -125,27 +125,25 @@ row_sel_sec_rec_is_for_blob( return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); } -/************************************************************************ +/********************************************************************//** Returns TRUE if the user-defined column values in a secondary index record are alphabetically the same as the corresponding columns in the clustered index record. NOTE: the comparison is NOT done as a binary comparison, but character -fields are compared with collation! */ +fields are compared with collation! +@return TRUE if the secondary record is equal to the corresponding +fields in the clustered record, when compared with collation */ static ibool row_sel_sec_rec_is_for_clust_rec( /*=============================*/ - /* out: TRUE if the secondary - record is equal to the corresponding - fields in the clustered record, - when compared with collation */ - const rec_t* sec_rec, /* in: secondary index record */ - dict_index_t* sec_index, /* in: secondary index */ - const rec_t* clust_rec, /* in: clustered index record; + const rec_t* sec_rec, /*!< in: secondary index record */ + dict_index_t* sec_index, /*!< in: secondary index */ + const rec_t* clust_rec, /*!< in: clustered index record; must be protected by a lock or a page latch against deletion in rollback or purge */ - dict_index_t* clust_index) /* in: clustered index */ + dict_index_t* clust_index) /*!< in: clustered index */ { const byte* sec_field; ulint sec_len; @@ -238,14 +236,14 @@ func_exit: return(is_equal); } -/************************************************************************* -Creates a select node struct. */ +/*********************************************************************//** +Creates a select node struct. +@return own: select node struct */ UNIV_INTERN sel_node_t* sel_node_create( /*============*/ - /* out, own: select node struct */ - mem_heap_t* heap) /* in: memory heap where created */ + mem_heap_t* heap) /*!< in: memory heap where created */ { sel_node_t* node; @@ -258,14 +256,14 @@ sel_node_create( return(node); } -/************************************************************************* +/*********************************************************************//** Frees the memory private to a select node when a query graph is freed, does not free the heap where the node was originally created. */ UNIV_INTERN void sel_node_free_private( /*==================*/ - sel_node_t* node) /* in: select node struct */ + sel_node_t* node) /*!< in: select node struct */ { ulint i; plan_t* plan; @@ -284,14 +282,14 @@ sel_node_free_private( } } -/************************************************************************* +/*********************************************************************//** Evaluates the values in a select list. If there are aggregate functions, their argument value is added to the aggregate total. */ UNIV_INLINE void sel_eval_select_list( /*=================*/ - sel_node_t* node) /* in: select node */ + sel_node_t* node) /*!< in: select node */ { que_node_t* exp; @@ -304,15 +302,15 @@ sel_eval_select_list( } } -/************************************************************************* +/*********************************************************************//** Assigns the values in the select list to the possible into-variables in SELECT ... INTO ... */ UNIV_INLINE void sel_assign_into_var_values( /*=======================*/ - sym_node_t* var, /* in: first variable in a list of variables */ - sel_node_t* node) /* in: select node */ + sym_node_t* var, /*!< in: first variable in a list of variables */ + sel_node_t* node) /*!< in: select node */ { que_node_t* exp; @@ -333,14 +331,14 @@ sel_assign_into_var_values( } } -/************************************************************************* +/*********************************************************************//** Resets the aggregate value totals in the select list of an aggregate type query. */ UNIV_INLINE void sel_reset_aggregate_vals( /*=====================*/ - sel_node_t* node) /* in: select node */ + sel_node_t* node) /*!< in: select node */ { func_node_t* func_node; @@ -357,13 +355,13 @@ sel_reset_aggregate_vals( node->aggregate_already_fetched = FALSE; } -/************************************************************************* +/*********************************************************************//** Copies the input variable values when an explicit cursor is opened. */ UNIV_INLINE void row_sel_copy_input_variable_vals( /*=============================*/ - sel_node_t* node) /* in: select node */ + sel_node_t* node) /*!< in: select node */ { sym_node_t* var; @@ -378,17 +376,17 @@ row_sel_copy_input_variable_vals( } } -/************************************************************************* +/*********************************************************************//** Fetches the column values from a record. */ static void row_sel_fetch_columns( /*==================*/ - dict_index_t* index, /* in: record index */ - const rec_t* rec, /* in: record in a clustered or non-clustered + dict_index_t* index, /*!< in: record index */ + const rec_t* rec, /*!< in: record in a clustered or non-clustered index; must be protected by a page latch */ - const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - sym_node_t* column) /* in: first column in a column list, or + const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + sym_node_t* column) /*!< in: first column in a column list, or NULL */ { dfield_t* val; @@ -457,13 +455,13 @@ row_sel_fetch_columns( } } -/************************************************************************* +/*********************************************************************//** Allocates a prefetch buffer for a column when prefetch is first time done. */ static void sel_col_prefetch_buf_alloc( /*=======================*/ - sym_node_t* column) /* in: symbol table node for a column */ + sym_node_t* column) /*!< in: symbol table node for a column */ { sel_buf_t* sel_buf; ulint i; @@ -481,14 +479,14 @@ sel_col_prefetch_buf_alloc( } } -/************************************************************************* +/*********************************************************************//** Frees a prefetch buffer for a column, including the dynamically allocated memory for data stored there. */ UNIV_INTERN void sel_col_prefetch_buf_free( /*======================*/ - sel_buf_t* prefetch_buf) /* in, own: prefetch buffer */ + sel_buf_t* prefetch_buf) /*!< in, own: prefetch buffer */ { sel_buf_t* sel_buf; ulint i; @@ -503,14 +501,14 @@ sel_col_prefetch_buf_free( } } -/************************************************************************* +/*********************************************************************//** Pops the column values for a prefetched, cached row from the column prefetch buffers and places them to the val fields in the column nodes. */ static void sel_pop_prefetched_row( /*===================*/ - plan_t* plan) /* in: plan node for a table */ + plan_t* plan) /*!< in: plan node for a table */ { sym_node_t* column; sel_buf_t* sel_buf; @@ -565,14 +563,14 @@ next_col: plan->first_prefetched++; } -/************************************************************************* +/*********************************************************************//** Pushes the column values for a prefetched, cached row to the column prefetch buffers from the val fields in the column nodes. */ UNIV_INLINE void sel_push_prefetched_row( /*====================*/ - plan_t* plan) /* in: plan node for a table */ + plan_t* plan) /*!< in: plan node for a table */ { sym_node_t* column; sel_buf_t* sel_buf; @@ -637,26 +635,26 @@ next_col: } } -/************************************************************************* -Builds a previous version of a clustered index record for a consistent read */ +/*********************************************************************//** +Builds a previous version of a clustered index record for a consistent read +@return DB_SUCCESS or error code */ static ulint row_sel_build_prev_vers( /*====================*/ - /* out: DB_SUCCESS or error code */ - read_view_t* read_view, /* in: read view */ - dict_index_t* index, /* in: plan node for table */ - rec_t* rec, /* in: record in a clustered index */ - ulint** offsets, /* in/out: offsets returned by + read_view_t* read_view, /*!< in: read view */ + dict_index_t* index, /*!< in: plan node for table */ + rec_t* rec, /*!< in: record in a clustered index */ + ulint** offsets, /*!< in/out: offsets returned by rec_get_offsets(rec, plan->index) */ - mem_heap_t** offset_heap, /* in/out: memory heap from which + mem_heap_t** offset_heap, /*!< in/out: memory heap from which the offsets are allocated */ - mem_heap_t** old_vers_heap, /* out: old version heap to use */ - rec_t** old_vers, /* out: old version, or NULL if the + mem_heap_t** old_vers_heap, /*!< out: old version heap to use */ + rec_t** old_vers, /*!< out: old version, or NULL if the record does not exist in the view: i.e., it was freshly inserted afterwards */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { ulint err; @@ -672,26 +670,26 @@ row_sel_build_prev_vers( return(err); } -/************************************************************************* +/*********************************************************************//** Builds the last committed version of a clustered index record for a -semi-consistent read. */ +semi-consistent read. +@return DB_SUCCESS or error code */ static ulint row_sel_build_committed_vers_for_mysql( /*===================================*/ - /* out: DB_SUCCESS or error code */ - dict_index_t* clust_index, /* in: clustered index */ - row_prebuilt_t* prebuilt, /* in: prebuilt struct */ - const rec_t* rec, /* in: record in a clustered index */ - ulint** offsets, /* in/out: offsets returned by + dict_index_t* clust_index, /*!< in: clustered index */ + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ + const rec_t* rec, /*!< in: record in a clustered index */ + ulint** offsets, /*!< in/out: offsets returned by rec_get_offsets(rec, clust_index) */ - mem_heap_t** offset_heap, /* in/out: memory heap from which + mem_heap_t** offset_heap, /*!< in/out: memory heap from which the offsets are allocated */ - const rec_t** old_vers, /* out: old version, or NULL if the + const rec_t** old_vers, /*!< out: old version, or NULL if the record does not exist in the view: i.e., it was freshly inserted afterwards */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { ulint err; @@ -707,15 +705,15 @@ row_sel_build_committed_vers_for_mysql( return(err); } -/************************************************************************* +/*********************************************************************//** Tests the conditions which determine when the index segment we are searching -through has been exhausted. */ +through has been exhausted. +@return TRUE if row passed the tests */ UNIV_INLINE ibool row_sel_test_end_conds( /*===================*/ - /* out: TRUE if row passed the tests */ - plan_t* plan) /* in: plan for the table; the column values must + plan_t* plan) /*!< in: plan for the table; the column values must already have been retrieved and the right sides of comparisons evaluated */ { @@ -745,14 +743,14 @@ row_sel_test_end_conds( return(TRUE); } -/************************************************************************* -Tests the other conditions. */ +/*********************************************************************//** +Tests the other conditions. +@return TRUE if row passed the tests */ UNIV_INLINE ibool row_sel_test_other_conds( /*=====================*/ - /* out: TRUE if row passed the tests */ - plan_t* plan) /* in: plan for the table; the column values must + plan_t* plan) /*!< in: plan for the table; the column values must already have been retrieved */ { func_node_t* cond; @@ -773,23 +771,23 @@ row_sel_test_other_conds( return(TRUE); } -/************************************************************************* +/*********************************************************************//** Retrieves the clustered index record corresponding to a record in a -non-clustered index. Does the necessary locking. */ +non-clustered index. Does the necessary locking. +@return DB_SUCCESS or error code */ static ulint row_sel_get_clust_rec( /*==================*/ - /* out: DB_SUCCESS or error code */ - sel_node_t* node, /* in: select_node */ - plan_t* plan, /* in: plan node for table */ - rec_t* rec, /* in: record in a non-clustered index */ - que_thr_t* thr, /* in: query thread */ - rec_t** out_rec,/* out: clustered record or an old version of + sel_node_t* node, /*!< in: select_node */ + plan_t* plan, /*!< in: plan node for table */ + rec_t* rec, /*!< in: record in a non-clustered index */ + que_thr_t* thr, /*!< in: query thread */ + rec_t** out_rec,/*!< out: clustered record or an old version of it, NULL if the old version did not exist in the read view, i.e., it was a fresh inserted version */ - mtr_t* mtr) /* in: mtr used to get access to the + mtr_t* mtr) /*!< in: mtr used to get access to the non-clustered record; the same mtr is used to access the clustered index */ { @@ -937,21 +935,21 @@ err_exit: return(err); } -/************************************************************************* -Sets a lock on a record. */ +/*********************************************************************//** +Sets a lock on a record. +@return DB_SUCCESS or error code */ UNIV_INLINE ulint sel_set_rec_lock( /*=============*/ - /* out: DB_SUCCESS or error code */ - const buf_block_t* block, /* in: buffer block of rec */ - const rec_t* rec, /* in: record */ - dict_index_t* index, /* in: index */ - const ulint* offsets,/* in: rec_get_offsets(rec, index) */ - ulint mode, /* in: lock mode */ - ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or + const buf_block_t* block, /*!< in: buffer block of rec */ + const rec_t* rec, /*!< in: record */ + dict_index_t* index, /*!< in: index */ + const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + ulint mode, /*!< in: lock mode */ + ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; ulint err; @@ -976,18 +974,18 @@ sel_set_rec_lock( return(err); } -/************************************************************************* +/*********************************************************************//** Opens a pcur to a table index. */ static void row_sel_open_pcur( /*==============*/ - plan_t* plan, /* in: table plan */ + plan_t* plan, /*!< in: table plan */ ibool search_latch_locked, - /* in: TRUE if the thread currently + /*!< in: TRUE if the thread currently has the search latch locked in s-mode */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { dict_index_t* index; func_node_t* cond; @@ -1051,19 +1049,18 @@ row_sel_open_pcur( plan->pcur_is_open = TRUE; } -/************************************************************************* -Restores a stored pcur position to a table index. */ +/*********************************************************************//** +Restores a stored pcur position to a table index. +@return TRUE if the cursor should be moved to the next record after we +return from this function (moved to the previous, in the case of a +descending cursor) without processing again the current cursor +record */ static ibool row_sel_restore_pcur_pos( /*=====================*/ - /* out: TRUE if the cursor should be moved to - the next record after we return from this - function (moved to the previous, in the case - of a descending cursor) without processing - again the current cursor record */ - plan_t* plan, /* in: table plan */ - mtr_t* mtr) /* in: mtr */ + plan_t* plan, /*!< in: table plan */ + mtr_t* mtr) /*!< in: mtr */ { ibool equal_position; ulint relative_position; @@ -1147,13 +1144,13 @@ row_sel_restore_pcur_pos( return(TRUE); } -/************************************************************************* +/*********************************************************************//** Resets a plan cursor to a closed state. */ UNIV_INLINE void plan_reset_cursor( /*==============*/ - plan_t* plan) /* in: plan */ + plan_t* plan) /*!< in: plan */ { plan->pcur_is_open = FALSE; plan->cursor_at_end = FALSE; @@ -1161,18 +1158,18 @@ plan_reset_cursor( plan->n_rows_prefetched = 0; } -/************************************************************************* +/*********************************************************************//** Tries to do a shortcut to fetch a clustered index record with a unique key, -using the hash index if possible (not always). */ +using the hash index if possible (not always). +@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */ static ulint row_sel_try_search_shortcut( /*========================*/ - /* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */ - sel_node_t* node, /* in: select node for a consistent read */ - plan_t* plan, /* in: plan for a unique search in clustered + sel_node_t* node, /*!< in: select node for a consistent read */ + plan_t* plan, /*!< in: plan for a unique search in clustered index */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { dict_index_t* index; rec_t* rec; @@ -1263,15 +1260,15 @@ func_exit: return(ret); } -/************************************************************************* -Performs a select step. */ +/*********************************************************************//** +Performs a select step. +@return DB_SUCCESS or error code */ static ulint row_sel( /*====*/ - /* out: DB_SUCCESS or error code */ - sel_node_t* node, /* in: select node */ - que_thr_t* thr) /* in: query thread */ + sel_node_t* node, /*!< in: select node */ + que_thr_t* thr) /*!< in: query thread */ { dict_index_t* index; plan_t* plan; @@ -1964,15 +1961,15 @@ func_exit: return(err); } -/************************************************************************** +/**********************************************************************//** Performs a select step. This is a high-level function used in SQL execution -graphs. */ +graphs. +@return query thread to run next or NULL */ UNIV_INTERN que_thr_t* row_sel_step( /*=========*/ - /* out: query thread to run next or NULL */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /*!< in: query thread */ { ulint i_lock_mode; sym_node_t* table_node; @@ -2066,14 +2063,14 @@ row_sel_step( return(thr); } -/************************************************************************** -Performs a fetch for a cursor. */ +/**********************************************************************//** +Performs a fetch for a cursor. +@return query thread to run next or NULL */ UNIV_INTERN que_thr_t* fetch_step( /*=======*/ - /* out: query thread to run next or NULL */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /*!< in: query thread */ { sel_node_t* sel_node; fetch_node_t* node; @@ -2129,15 +2126,15 @@ fetch_step( return(thr); } -/******************************************************************** -Sample callback function for fetch that prints each row.*/ +/****************************************************************//** +Sample callback function for fetch that prints each row. +@return always returns non-NULL */ UNIV_INTERN void* row_fetch_print( /*============*/ - /* out: always returns non-NULL */ - void* row, /* in: sel_node_t* */ - void* user_arg) /* in: not used */ + void* row, /*!< in: sel_node_t* */ + void* user_arg) /*!< in: not used */ { sel_node_t* node = row; que_node_t* exp; @@ -2173,17 +2170,17 @@ row_fetch_print( return((void*)42); } -/******************************************************************** +/****************************************************************//** Callback function for fetch that stores an unsigned 4 byte integer to the location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length -= 4. */ += 4. +@return always returns NULL */ UNIV_INTERN void* row_fetch_store_uint4( /*==================*/ - /* out: always returns NULL */ - void* row, /* in: sel_node_t* */ - void* user_arg) /* in: data pointer */ + void* row, /*!< in: sel_node_t* */ + void* user_arg) /*!< in: data pointer */ { sel_node_t* node = row; ib_uint32_t* val = user_arg; @@ -2203,14 +2200,14 @@ row_fetch_store_uint4( return(NULL); } -/*************************************************************** -Prints a row in a select result. */ +/***********************************************************//** +Prints a row in a select result. +@return query thread to run next or NULL */ UNIV_INTERN que_thr_t* row_printf_step( /*============*/ - /* out: query thread to run next or NULL */ - que_thr_t* thr) /* in: query thread */ + que_thr_t* thr) /*!< in: query thread */ { row_printf_node_t* node; sel_node_t* sel_node; @@ -2266,7 +2263,7 @@ row_printf_step( return(thr); } -/******************************************************************** +/****************************************************************//** Converts a key value stored in MySQL format to an Innobase dtuple. The last field of the key value may be just a prefix of a fixed length field: hence the parameter key_len. But currently we do not allow search keys where the @@ -2277,17 +2274,17 @@ UNIV_INTERN void row_sel_convert_mysql_key_to_innobase( /*==================================*/ - dtuple_t* tuple, /* in/out: tuple where to build; + dtuple_t* tuple, /*!< in/out: tuple where to build; NOTE: we assume that the type info in the tuple is already according to index! */ - byte* buf, /* in: buffer to use in field + byte* buf, /*!< in: buffer to use in field conversions */ - ulint buf_len, /* in: buffer length */ - dict_index_t* index, /* in: index of the key value */ - const byte* key_ptr, /* in: MySQL key value */ - ulint key_len, /* in: MySQL key value length */ - trx_t* trx) /* in: transaction */ + ulint buf_len, /*!< in: buffer length */ + dict_index_t* index, /*!< in: index of the key value */ + const byte* key_ptr, /*!< in: MySQL key value */ + ulint key_len, /*!< in: MySQL key value length */ + trx_t* trx) /*!< in: transaction */ { byte* original_buf = buf; const byte* original_key_ptr = key_ptr; @@ -2470,16 +2467,16 @@ row_sel_convert_mysql_key_to_innobase( dtuple_set_n_fields(tuple, n_fields); } -/****************************************************************** +/**************************************************************//** Stores the row id to the prebuilt struct. */ static void row_sel_store_row_id_to_prebuilt( /*=============================*/ - row_prebuilt_t* prebuilt, /* in/out: prebuilt */ - const rec_t* index_rec, /* in: record */ - const dict_index_t* index, /* in: index of the record */ - const ulint* offsets) /* in: rec_get_offsets + row_prebuilt_t* prebuilt, /*!< in/out: prebuilt */ + const rec_t* index_rec, /*!< in: record */ + const dict_index_t* index, /*!< in: index of the record */ + const ulint* offsets) /*!< in: rec_get_offsets (index_rec, index) */ { const byte* data; @@ -2508,26 +2505,26 @@ row_sel_store_row_id_to_prebuilt( ut_memcpy(prebuilt->row_id, data, len); } -/****************************************************************** +/**************************************************************//** Stores a non-SQL-NULL field in the MySQL format. The counterpart of this function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */ static void row_sel_field_store_in_mysql_format( /*================================*/ - byte* dest, /* in/out: buffer where to store; NOTE + byte* dest, /*!< in/out: buffer where to store; NOTE that BLOBs are not in themselves stored here: the caller must allocate and copy the BLOB into buffer before, and pass the pointer to the BLOB in 'data' */ const mysql_row_templ_t* templ, - /* in: MySQL column template. + /*!< in: MySQL column template. Its following fields are referenced: type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen */ - const byte* data, /* in: data to store */ - ulint len) /* in: length of the data */ + const byte* data, /*!< in: data to store */ + ulint len) /*!< in: length of the data */ { byte* ptr; byte* field_end; @@ -2663,26 +2660,24 @@ row_sel_field_store_in_mysql_format( } } -/****************************************************************** +/**************************************************************//** Convert a row in the Innobase format to a row in the MySQL format. Note that the template in prebuilt may advise us to copy only a few columns to mysql_rec, other columns are left blank. All columns may not -be needed in the query. */ +be needed in the query. +@return TRUE if success, FALSE if could not allocate memory for a BLOB +(though we may also assert in that case) */ static ibool row_sel_store_mysql_rec( /*====================*/ - /* out: TRUE if success, FALSE if - could not allocate memory for a BLOB - (though we may also assert in that - case) */ - byte* mysql_rec, /* out: row in the MySQL format */ - row_prebuilt_t* prebuilt, /* in: prebuilt struct */ - const rec_t* rec, /* in: Innobase record in the index + byte* mysql_rec, /*!< out: row in the MySQL format */ + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ + const rec_t* rec, /*!< in: Innobase record in the index which was described in prebuilt's template; must be protected by a page latch */ - const ulint* offsets) /* in: array returned by + const ulint* offsets) /*!< in: array returned by rec_get_offsets() */ { mysql_row_templ_t* templ; @@ -2787,7 +2782,8 @@ row_sel_store_mysql_rec( mysql_rec[templ->mysql_null_byte_offset] |= (byte) templ->mysql_null_bit_mask; memcpy(mysql_rec + templ->mysql_col_offset, - prebuilt->default_rec + templ->mysql_col_offset, + (const byte*) prebuilt->default_rec + + templ->mysql_col_offset, templ->mysql_col_len); } } @@ -2795,26 +2791,26 @@ row_sel_store_mysql_rec( return(TRUE); } -/************************************************************************* -Builds a previous version of a clustered index record for a consistent read */ +/*********************************************************************//** +Builds a previous version of a clustered index record for a consistent read +@return DB_SUCCESS or error code */ static ulint row_sel_build_prev_vers_for_mysql( /*==============================*/ - /* out: DB_SUCCESS or error code */ - read_view_t* read_view, /* in: read view */ - dict_index_t* clust_index, /* in: clustered index */ - row_prebuilt_t* prebuilt, /* in: prebuilt struct */ - const rec_t* rec, /* in: record in a clustered index */ - ulint** offsets, /* in/out: offsets returned by + read_view_t* read_view, /*!< in: read view */ + dict_index_t* clust_index, /*!< in: clustered index */ + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ + const rec_t* rec, /*!< in: record in a clustered index */ + ulint** offsets, /*!< in/out: offsets returned by rec_get_offsets(rec, clust_index) */ - mem_heap_t** offset_heap, /* in/out: memory heap from which + mem_heap_t** offset_heap, /*!< in/out: memory heap from which the offsets are allocated */ - rec_t** old_vers, /* out: old version, or NULL if the + rec_t** old_vers, /*!< out: old version, or NULL if the record does not exist in the view: i.e., it was freshly inserted afterwards */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr) /*!< in: mtr */ { ulint err; @@ -2830,33 +2826,33 @@ row_sel_build_prev_vers_for_mysql( return(err); } -/************************************************************************* +/*********************************************************************//** Retrieves the clustered index record corresponding to a record in a non-clustered index. Does the necessary locking. Used in the MySQL -interface. */ +interface. +@return DB_SUCCESS or error code */ static ulint row_sel_get_clust_rec_for_mysql( /*============================*/ - /* out: DB_SUCCESS or error code */ - row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */ - dict_index_t* sec_index,/* in: secondary index where rec resides */ - const rec_t* rec, /* in: record in a non-clustered index; if + row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */ + dict_index_t* sec_index,/*!< in: secondary index where rec resides */ + const rec_t* rec, /*!< in: record in a non-clustered index; if this is a locking read, then rec is not allowed to be delete-marked, and that would not make sense either */ - que_thr_t* thr, /* in: query thread */ - const rec_t** out_rec,/* out: clustered record or an old version of + que_thr_t* thr, /*!< in: query thread */ + const rec_t** out_rec,/*!< out: clustered record or an old version of it, NULL if the old version did not exist in the read view, i.e., it was a fresh inserted version */ - ulint** offsets,/* in: offsets returned by + ulint** offsets,/*!< in: offsets returned by rec_get_offsets(rec, sec_index); out: offsets returned by rec_get_offsets(out_rec, clust_index) */ - mem_heap_t** offset_heap,/* in/out: memory heap from which + mem_heap_t** offset_heap,/*!< in/out: memory heap from which the offsets are allocated */ - mtr_t* mtr) /* in: mtr used to get access to the + mtr_t* mtr) /*!< in: mtr used to get access to the non-clustered record; the same mtr is used to access the clustered index */ { @@ -3014,29 +3010,27 @@ err_exit: return(err); } -/************************************************************************ +/********************************************************************//** Restores cursor position after it has been stored. We have to take into account that the record cursor was positioned on may have been deleted. -Then we may have to move the cursor one step up or down. */ +Then we may have to move the cursor one step up or down. +@return TRUE if we may need to process the record the cursor is now +positioned on (i.e. we should not go to the next record yet) */ static ibool sel_restore_position_for_mysql( /*===========================*/ - /* out: TRUE if we may need to - process the record the cursor is - now positioned on (i.e. we should - not go to the next record yet) */ - ibool* same_user_rec, /* out: TRUE if we were able to restore + ibool* same_user_rec, /*!< out: TRUE if we were able to restore the cursor on a user record with the same ordering prefix in in the B-tree index */ - ulint latch_mode, /* in: latch mode wished in + ulint latch_mode, /*!< in: latch mode wished in restoration */ - btr_pcur_t* pcur, /* in: cursor whose position + btr_pcur_t* pcur, /*!< in: cursor whose position has been stored */ - ibool moves_up, /* in: TRUE if the cursor moves up + ibool moves_up, /*!< in: TRUE if the cursor moves up in the index */ - mtr_t* mtr) /* in: mtr; CAUTION: may commit + mtr_t* mtr) /*!< in: mtr; CAUTION: may commit mtr temporarily! */ { ibool success; @@ -3084,15 +3078,15 @@ sel_restore_position_for_mysql( return(TRUE); } -/************************************************************************ +/********************************************************************//** Pops a cached row for MySQL from the fetch cache. */ UNIV_INLINE void row_sel_pop_cached_row_for_mysql( /*=============================*/ - byte* buf, /* in/out: buffer where to copy the + byte* buf, /*!< in/out: buffer where to copy the row */ - row_prebuilt_t* prebuilt) /* in: prebuilt struct */ + row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */ { ulint i; mysql_row_templ_t* templ; @@ -3134,16 +3128,16 @@ row_sel_pop_cached_row_for_mysql( } } -/************************************************************************ +/********************************************************************//** Pushes a row for MySQL to the fetch cache. */ UNIV_INLINE void row_sel_push_cache_row_for_mysql( /*=============================*/ - row_prebuilt_t* prebuilt, /* in: prebuilt struct */ - const rec_t* rec, /* in: record to push; must + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ + const rec_t* rec, /*!< in: record to push; must be protected by a page latch */ - const ulint* offsets) /* in: rec_get_offsets() */ + const ulint* offsets) /*!< in: rec_get_offsets() */ { byte* buf; ulint i; @@ -3183,21 +3177,21 @@ row_sel_push_cache_row_for_mysql( prebuilt->n_fetch_cached++; } -/************************************************************************* +/*********************************************************************//** Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always). We assume that the search mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx, -btr search latch has been locked in S-mode. */ +btr search latch has been locked in S-mode. +@return SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */ static ulint row_sel_try_search_shortcut_for_mysql( /*==================================*/ - /* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */ - const rec_t** out_rec,/* out: record if found */ - row_prebuilt_t* prebuilt,/* in: prebuilt struct */ - ulint** offsets,/* in/out: for rec_get_offsets(*out_rec) */ - mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */ - mtr_t* mtr) /* in: started mtr */ + const rec_t** out_rec,/*!< out: record if found */ + row_prebuilt_t* prebuilt,/*!< in: prebuilt struct */ + ulint** offsets,/*!< in/out: for rec_get_offsets(*out_rec) */ + mem_heap_t** heap, /*!< in/out: heap for rec_get_offsets() */ + mtr_t* mtr) /*!< in: started mtr */ { dict_index_t* index = prebuilt->index; const dtuple_t* search_tuple = prebuilt->search_tuple; @@ -3254,34 +3248,31 @@ row_sel_try_search_shortcut_for_mysql( return(SEL_FOUND); } -/************************************************************************ +/********************************************************************//** Searches for rows in the database. This is used in the interface to MySQL. This function opens a cursor, and also implements fetch next and fetch prev. NOTE that if we do a search with a full key value from a unique index (ROW_SEL_EXACT), then we will not store the cursor -position and fetch next or fetch prev must not be tried to the cursor! */ +position and fetch next or fetch prev must not be tried to the cursor! +@return DB_SUCCESS, DB_RECORD_NOT_FOUND, DB_END_OF_INDEX, DB_DEADLOCK, +DB_LOCK_TABLE_FULL, DB_CORRUPTION, or DB_TOO_BIG_RECORD */ UNIV_INTERN ulint row_search_for_mysql( /*=================*/ - /* out: DB_SUCCESS, - DB_RECORD_NOT_FOUND, - DB_END_OF_INDEX, DB_DEADLOCK, - DB_LOCK_TABLE_FULL, DB_CORRUPTION, - or DB_TOO_BIG_RECORD */ - byte* buf, /* in/out: buffer for the fetched + byte* buf, /*!< in/out: buffer for the fetched row in the MySQL format */ - ulint mode, /* in: search mode PAGE_CUR_L, ... */ - row_prebuilt_t* prebuilt, /* in: prebuilt struct for the + ulint mode, /*!< in: search mode PAGE_CUR_L, ... */ + row_prebuilt_t* prebuilt, /*!< in: prebuilt struct for the table handle; this contains the info of search_tuple, index; if search tuple contains 0 fields then we position the cursor at the start or the end of the index, depending on 'mode' */ - ulint match_mode, /* in: 0 or ROW_SEL_EXACT or + ulint match_mode, /*!< in: 0 or ROW_SEL_EXACT or ROW_SEL_EXACT_PREFIX */ - ulint direction) /* in: 0 or ROW_SEL_NEXT or + ulint direction) /*!< in: 0 or ROW_SEL_NEXT or ROW_SEL_PREV; NOTE: if this is != 0, then prebuilt must have a pcur with stored position! In opening of a @@ -3335,14 +3326,18 @@ row_search_for_mysql( "InnoDB: the MySQL datadir, or have you used" " DISCARD TABLESPACE?\n" "InnoDB: Look from\n" - "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/" - "innodb-troubleshooting.html\n" + "InnoDB: " REFMAN "innodb-troubleshooting.html\n" "InnoDB: how you can resolve the problem.\n", prebuilt->table->name); return(DB_ERROR); } + if (UNIV_UNLIKELY(!prebuilt->index_usable)) { + + return(DB_MISSING_HISTORY); + } + if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" @@ -4554,17 +4549,16 @@ func_exit: return(err); } -/*********************************************************************** +/*******************************************************************//** Checks if MySQL at the moment is allowed for this table to retrieve a -consistent read result, or store it to the query cache. */ +consistent read result, or store it to the query cache. +@return TRUE if storing or retrieving from the query cache is permitted */ UNIV_INTERN ibool row_search_check_if_query_cache_permitted( /*======================================*/ - /* out: TRUE if storing or retrieving - from the query cache is permitted */ - trx_t* trx, /* in: transaction object */ - const char* norm_name) /* in: concatenation of database name, + trx_t* trx, /*!< in: transaction object */ + const char* norm_name) /*!< in: concatenation of database name, '/' char, table name */ { dict_table_t* table; @@ -4611,18 +4605,18 @@ row_search_check_if_query_cache_permitted( return(ret); } -/*********************************************************************** +/*******************************************************************//** Read the AUTOINC column from the current row. If the value is less than -0 and the type is not unsigned then we reset the value to 0. */ +0 and the type is not unsigned then we reset the value to 0. +@return value read from the column */ static ib_uint64_t row_search_autoinc_read_column( /*===========================*/ - /* out: value read from the column */ - dict_index_t* index, /* in: index to read from */ - const rec_t* rec, /* in: current rec */ - ulint col_no, /* in: column number */ - ibool unsigned_type) /* in: signed or unsigned flag */ + dict_index_t* index, /*!< in: index to read from */ + const rec_t* rec, /*!< in: current rec */ + ulint col_no, /*!< in: column number */ + ibool unsigned_type) /*!< in: signed or unsigned flag */ { ulint len; const byte* data; @@ -4654,15 +4648,15 @@ row_search_autoinc_read_column( return(value); } -/*********************************************************************** -Get the last row. */ +/*******************************************************************//** +Get the last row. +@return current rec or NULL */ static const rec_t* row_search_autoinc_get_rec( /*=======================*/ - /* out: current rec or NULL */ - btr_pcur_t* pcur, /* in: the current cursor */ - mtr_t* mtr) /* in: mini transaction */ + btr_pcur_t* pcur, /*!< in: the current cursor */ + mtr_t* mtr) /*!< in: mini transaction */ { do { const rec_t* rec = btr_pcur_get_rec(pcur); @@ -4675,18 +4669,17 @@ row_search_autoinc_get_rec( return(NULL); } -/*********************************************************************** -Read the max AUTOINC value from an index. */ +/*******************************************************************//** +Read the max AUTOINC value from an index. +@return DB_SUCCESS if all OK else error code, DB_RECORD_NOT_FOUND if +column name can't be found in index */ UNIV_INTERN ulint row_search_max_autoinc( /*===================*/ - /* out: DB_SUCCESS if all OK else - error code, DB_RECORD_NOT_FOUND if - column name can't be found in index */ - dict_index_t* index, /* in: index to search */ - const char* col_name, /* in: name of autoinc column */ - ib_uint64_t* value) /* out: AUTOINC value read */ + dict_index_t* index, /*!< in: index to search */ + const char* col_name, /*!< in: name of autoinc column */ + ib_uint64_t* value) /*!< out: AUTOINC value read */ { ulint i; ulint n_cols; |