diff options
Diffstat (limited to 'storage/innobase/include/row0merge.h')
-rw-r--r-- | storage/innobase/include/row0merge.h | 284 |
1 files changed, 165 insertions, 119 deletions
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h index c4e2f5ddf41..f464e46ae5b 100644 --- a/storage/innobase/include/row0merge.h +++ b/storage/innobase/include/row0merge.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2010, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2012, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -40,15 +40,17 @@ Created 13/06/2005 Jan Lindstrom #include "lock0types.h" #include "srv0srv.h" +// Forward declaration +struct ib_sequence_t; + /** @brief Block size for I/O operations in merge sort. The minimum is UNIV_PAGE_SIZE, or page_get_free_space_of_empty() rounded to a power of 2. When not creating a PRIMARY KEY that contains column prefixes, this -can be set as small as UNIV_PAGE_SIZE / 2. See the comment above -ut_ad(data_size < sizeof(row_merge_block_t)). */ -typedef byte row_merge_block_t; +can be set as small as UNIV_PAGE_SIZE / 2. */ +typedef byte row_merge_block_t; /** @brief Secondary buffer for I/O operations of merge records. @@ -64,114 +66,146 @@ The format is the same as a record in ROW_FORMAT=COMPACT with the exception that the REC_N_NEW_EXTRA_BYTES are omitted. */ typedef byte mrec_t; +/** Merge record in row_merge_buf_t */ +struct mtuple_t { + dfield_t* fields; /*!< data fields */ +}; + /** Buffer for sorting in main memory. */ -struct row_merge_buf_struct { +struct row_merge_buf_t { mem_heap_t* heap; /*!< memory heap where allocated */ dict_index_t* index; /*!< the index the tuples belong to */ ulint total_size; /*!< total amount of data bytes */ ulint n_tuples; /*!< number of data tuples */ ulint max_tuples; /*!< maximum number of data tuples */ - const dfield_t**tuples; /*!< array of pointers to - arrays of fields that form - the data tuples */ - const dfield_t**tmp_tuples; /*!< temporary copy of tuples, + mtuple_t* tuples; /*!< array of data tuples */ + mtuple_t* tmp_tuples; /*!< temporary copy of tuples, for sorting */ }; -/** Buffer for sorting in main memory. */ -typedef struct row_merge_buf_struct row_merge_buf_t; - /** Information about temporary files used in merge sort */ -struct merge_file_struct { +struct merge_file_t { int fd; /*!< file descriptor */ ulint offset; /*!< file offset (end of file) */ ib_uint64_t n_rec; /*!< number of records in the file */ }; -/** Information about temporary files used in merge sort */ -typedef struct merge_file_struct merge_file_t; - /** Index field definition */ -struct merge_index_field_struct { +struct index_field_t { + ulint col_no; /*!< column offset */ ulint prefix_len; /*!< column prefix length, or 0 if indexing the whole column */ - const char* field_name; /*!< field name */ }; -/** Index field definition */ -typedef struct merge_index_field_struct merge_index_field_t; - /** Definition of an index being created */ -struct merge_index_def_struct { - const char* name; /*!< index name */ - ulint ind_type; /*!< 0, DICT_UNIQUE, - or DICT_CLUSTERED */ - ulint n_fields; /*!< number of fields - in index */ - merge_index_field_t* fields; /*!< field definitions */ +struct index_def_t { + const char* name; /*!< index name */ + ulint ind_type; /*!< 0, DICT_UNIQUE, + or DICT_CLUSTERED */ + ulint key_number; /*!< MySQL key number, + or ULINT_UNDEFINED if none */ + ulint n_fields; /*!< number of fields in index */ + index_field_t* fields; /*!< field definitions */ }; -/** Definition of an index being created */ -typedef struct merge_index_def_struct merge_index_def_t; - /** Structure for reporting duplicate records. */ -struct row_merge_dup_struct { - const dict_index_t* index; /*!< index being sorted */ - struct TABLE* table; /*!< MySQL table object */ - ulint n_dup; /*!< number of duplicates */ +struct row_merge_dup_t { + dict_index_t* index; /*!< index being sorted */ + struct TABLE* table; /*!< MySQL table object */ + const ulint* col_map;/*!< mapping of column numbers + in table to the rebuilt table + (index->table), or NULL if not + rebuilding table */ + ulint n_dup; /*!< number of duplicates */ }; -/** Structure for reporting duplicate records. */ -typedef struct row_merge_dup_struct row_merge_dup_t; - +/*************************************************************//** +Report a duplicate key. */ +UNIV_INTERN +void +row_merge_dup_report( +/*=================*/ + row_merge_dup_t* dup, /*!< in/out: for reporting duplicates */ + const dfield_t* entry) /*!< in: duplicate index entry */ + __attribute__((nonnull)); /*********************************************************************//** Sets an exclusive lock on a table, for the duration of creating indexes. @return error code or DB_SUCCESS */ UNIV_INTERN -ulint +dberr_t row_merge_lock_table( /*=================*/ trx_t* trx, /*!< in/out: transaction */ dict_table_t* table, /*!< in: table to lock */ - enum lock_mode mode); /*!< in: LOCK_X or LOCK_S */ + enum lock_mode mode) /*!< in: LOCK_X or LOCK_S */ + __attribute__((nonnull, warn_unused_result)); /*********************************************************************//** -Drop an index from the InnoDB system tables. The data dictionary must -have been locked exclusively by the caller, because the transaction -will not be committed. */ +Drop indexes that were created before an error occurred. +The data dictionary must have been locked exclusively by the caller, +because the transaction will not be committed. */ UNIV_INTERN void -row_merge_drop_index( -/*=================*/ - dict_index_t* index, /*!< in: index to be removed */ - dict_table_t* table, /*!< in: table */ - trx_t* trx); /*!< in: transaction handle */ +row_merge_drop_indexes_dict( +/*========================*/ + trx_t* trx, /*!< in/out: dictionary transaction */ + table_id_t table_id)/*!< in: table identifier */ + __attribute__((nonnull)); /*********************************************************************//** -Drop those indexes which were created before an error occurred when -building an index. The data dictionary must have been locked -exclusively by the caller, because the transaction will not be -committed. */ +Drop those indexes which were created before an error occurred. +The data dictionary must have been locked exclusively by the caller, +because the transaction will not be committed. */ UNIV_INTERN void row_merge_drop_indexes( /*===================*/ - trx_t* trx, /*!< in: transaction */ - dict_table_t* table, /*!< in: table containing the indexes */ - dict_index_t** index, /*!< in: indexes to drop */ - ulint num_created); /*!< in: number of elements in - index[] */ + trx_t* trx, /*!< in/out: transaction */ + dict_table_t* table, /*!< in/out: table containing the indexes */ + ibool locked) /*!< in: TRUE=table locked, + FALSE=may need to do a lazy drop */ + __attribute__((nonnull)); /*********************************************************************//** Drop all partially created indexes during crash recovery. */ UNIV_INTERN void row_merge_drop_temp_indexes(void); /*=============================*/ + +/*********************************************************************//** +Creates temporary merge files, and if UNIV_PFS_IO defined, register +the file descriptor with Performance Schema. +@return File descriptor */ +UNIV_INTERN +int +row_merge_file_create_low(void) +/*===========================*/ + __attribute__((warn_unused_result)); +/*********************************************************************//** +Destroy a merge file. And de-register the file from Performance Schema +if UNIV_PFS_IO is defined. */ +UNIV_INTERN +void +row_merge_file_destroy_low( +/*=======================*/ + int fd); /*!< in: merge file descriptor */ + +/*********************************************************************//** +Provide a new pathname for a table that is being renamed if it belongs to +a file-per-table tablespace. The caller is responsible for freeing the +memory allocated for the return value. +@return new pathname of tablespace file, or NULL if space = 0 */ +UNIV_INTERN +char* +row_make_new_pathname( +/*==================*/ + dict_table_t* table, /*!< in: table to be renamed */ + const char* new_name); /*!< in: new name */ /*********************************************************************//** Rename the tables in the data dictionary. The data dictionary must have been locked exclusively by the caller, because the transaction will not be committed. @return error code or DB_SUCCESS */ UNIV_INTERN -ulint +dberr_t row_merge_rename_tables( /*====================*/ dict_table_t* old_table, /*!< in/out: old table, renamed to @@ -179,32 +213,35 @@ row_merge_rename_tables( dict_table_t* new_table, /*!< in/out: new table, renamed to old_table->name */ const char* tmp_name, /*!< in: new name for old_table */ - trx_t* trx); /*!< in: transaction handle */ + trx_t* trx) /*!< in: transaction handle */ + __attribute__((nonnull, warn_unused_result)); + /*********************************************************************//** -Create a temporary table for creating a primary key, using the definition -of an existing table. -@return table, or NULL on error */ +Rename an index in the dictionary that was created. The data +dictionary must have been locked exclusively by the caller, because +the transaction will not be committed. +@return DB_SUCCESS if all OK */ UNIV_INTERN -dict_table_t* -row_merge_create_temporary_table( -/*=============================*/ - const char* table_name, /*!< in: new table name */ - const merge_index_def_t*index_def, /*!< in: the index definition - of the primary key */ - const dict_table_t* table, /*!< in: old table definition */ - trx_t* trx); /*!< in/out: transaction - (sets error_state) */ +dberr_t +row_merge_rename_index_to_add( +/*==========================*/ + trx_t* trx, /*!< in/out: transaction */ + table_id_t table_id, /*!< in: table identifier */ + index_id_t index_id) /*!< in: index identifier */ + __attribute__((nonnull)); /*********************************************************************//** -Rename the temporary indexes in the dictionary to permanent ones. The -data dictionary must have been locked exclusively by the caller, -because the transaction will not be committed. +Rename an index in the dictionary that is to be dropped. The data +dictionary must have been locked exclusively by the caller, because +the transaction will not be committed. @return DB_SUCCESS if all OK */ UNIV_INTERN -ulint -row_merge_rename_indexes( -/*=====================*/ +dberr_t +row_merge_rename_index_to_drop( +/*===========================*/ trx_t* trx, /*!< in/out: transaction */ - dict_table_t* table); /*!< in/out: table with new indexes */ + table_id_t table_id, /*!< in: table identifier */ + index_id_t index_id) /*!< in: index identifier */ + __attribute__((nonnull)); /*********************************************************************//** Create the index and load in to the dictionary. @return index, or NULL on error */ @@ -214,7 +251,7 @@ row_merge_create_index( /*===================*/ trx_t* trx, /*!< in/out: trx (sets error_state) */ dict_table_t* table, /*!< in: the index is on this table */ - const merge_index_def_t*index_def); + const index_def_t* index_def); /*!< in: the index definition */ /*********************************************************************//** Check if a transaction can use an index. @@ -226,22 +263,25 @@ row_merge_is_index_usable( const trx_t* trx, /*!< in: transaction */ const dict_index_t* index); /*!< in: index to check */ /*********************************************************************//** -If there are views that refer to the old table name then we "attach" to -the new instance of the table else we drop it immediately. +Drop a table. The caller must have ensured that the background stats +thread is not processing the table. This can be done by calling +dict_stats_wait_bg_to_stop_using_tables() after locking the dictionary and +before calling this function. @return DB_SUCCESS or error code */ UNIV_INTERN -ulint +dberr_t row_merge_drop_table( /*=================*/ trx_t* trx, /*!< in: transaction */ - dict_table_t* table); /*!< in: table instance to drop */ + dict_table_t* table) /*!< in: table instance to drop */ + __attribute__((nonnull)); /*********************************************************************//** Build indexes on a table by reading a clustered index, creating a temporary file containing index entries, merge sorting these index entries and inserting sorted index entries to indexes. @return DB_SUCCESS or error code */ UNIV_INTERN -ulint +dberr_t row_merge_build_indexes( /*====================*/ trx_t* trx, /*!< in: transaction */ @@ -250,11 +290,24 @@ row_merge_build_indexes( dict_table_t* new_table, /*!< in: table where indexes are created; identical to old_table unless creating a PRIMARY KEY */ + bool online, /*!< in: true if creating indexes + online */ dict_index_t** indexes, /*!< in: indexes to be created */ + const ulint* key_numbers, /*!< in: MySQL key numbers */ ulint n_indexes, /*!< in: size of indexes[] */ - struct TABLE* table); /*!< in/out: MySQL table, for + struct TABLE* table, /*!< in/out: MySQL table, for reporting erroneous key value if applicable */ + const dtuple_t* add_cols, /*!< in: default values of + added columns, or NULL */ + const ulint* col_map, /*!< in: mapping of old column + numbers to new ones, or NULL + if old_table == new_table */ + ulint add_autoinc, /*!< in: number of added + AUTO_INCREMENT column, or + ULINT_UNDEFINED if none is added */ + ib_sequence_t& sequence) /*!< in/out: autoinc sequence */ + __attribute__((nonnull(1,2,3,5,6,8), warn_unused_result)); /********************************************************************//** Write a buffer to a block. */ UNIV_INTERN @@ -263,15 +316,18 @@ row_merge_buf_write( /*================*/ const row_merge_buf_t* buf, /*!< in: sorted buffer */ const merge_file_t* of, /*!< in: output file */ - row_merge_block_t* block); /*!< out: buffer for writing to file */ + row_merge_block_t* block) /*!< out: buffer for writing to file */ + __attribute__((nonnull)); /********************************************************************//** Sort a buffer. */ UNIV_INTERN void row_merge_buf_sort( /*===============*/ - row_merge_buf_t* buf, /*!< in/out: sort buffer */ - row_merge_dup_t* dup); /*!< in/out: for reporting duplicates */ + row_merge_buf_t* buf, /*!< in/out: sort buffer */ + row_merge_dup_t* dup) /*!< in/out: reporter of duplicates + (NULL if non-unique index) */ + __attribute__((nonnull(1))); /********************************************************************//** Write a merge block to the file system. @return TRUE if request was successful, FALSE if fail */ @@ -290,30 +346,32 @@ UNIV_INTERN row_merge_buf_t* row_merge_buf_empty( /*================*/ - row_merge_buf_t* buf); /*!< in,own: sort buffer */ + row_merge_buf_t* buf) /*!< in,own: sort buffer */ + __attribute__((warn_unused_result, nonnull)); /*********************************************************************//** -Create a merge file. */ +Create a merge file. +@return file descriptor, or -1 on failure */ UNIV_INTERN -void +int row_merge_file_create( /*==================*/ - merge_file_t* merge_file); /*!< out: merge file structure */ + merge_file_t* merge_file) /*!< out: merge file structure */ + __attribute__((nonnull)); /*********************************************************************//** Merge disk files. @return DB_SUCCESS or error code */ UNIV_INTERN -ulint +dberr_t row_merge_sort( /*===========*/ trx_t* trx, /*!< in: transaction */ - const dict_index_t* index, /*!< in: index being created */ + const row_merge_dup_t* dup, /*!< in: descriptor of + index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ row_merge_block_t* block, /*!< in/out: 3 buffers */ - int* tmpfd, /*!< in/out: temporary file handle */ - struct TABLE* table); /*!< in/out: MySQL table, for - reporting erroneous key value - if applicable */ + int* tmpfd) /*!< in/out: temporary file handle */ + __attribute__((nonnull)); /*********************************************************************//** Allocate a sort buffer. @return own: sort buffer */ @@ -321,37 +379,24 @@ UNIV_INTERN row_merge_buf_t* row_merge_buf_create( /*=================*/ - dict_index_t* index); /*!< in: secondary index */ + dict_index_t* index) /*!< in: secondary index */ + __attribute__((warn_unused_result, nonnull, malloc)); /*********************************************************************//** Deallocate a sort buffer. */ UNIV_INTERN void row_merge_buf_free( /*===============*/ - row_merge_buf_t* buf); /*!< in,own: sort buffer, to be freed */ + row_merge_buf_t* buf) /*!< in,own: sort buffer to be freed */ + __attribute__((nonnull)); /*********************************************************************//** Destroy a merge file. */ UNIV_INTERN void row_merge_file_destroy( /*===================*/ - merge_file_t* merge_file); /*!< out: merge file structure */ -/*********************************************************************//** -Compare two merge records. -@return 1, 0, -1 if mrec1 is greater, equal, less, respectively, than mrec2 */ -UNIV_INTERN -int -row_merge_cmp( -/*==========*/ - const mrec_t* mrec1, /*!< in: first merge - record to be compared */ - const mrec_t* mrec2, /*!< in: second merge - record to be compared */ - const ulint* offsets1, /*!< in: first record offsets */ - const ulint* offsets2, /*!< in: second record offsets */ - const dict_index_t* index, /*!< in: index */ - ibool* null_eq); /*!< out: set to TRUE if - found matching null values */ + merge_file_t* merge_file) /*!< in/out: merge file structure */ + __attribute__((nonnull)); /********************************************************************//** Read a merge block from the file system. @return TRUE if request was successful, FALSE if fail */ @@ -367,7 +412,7 @@ row_merge_read( /********************************************************************//** Read a merge record. @return pointer to next record, or NULL on I/O error or end of list */ -UNIV_INTERN __attribute__((nonnull)) +UNIV_INTERN const byte* row_merge_read_rec( /*===============*/ @@ -380,5 +425,6 @@ row_merge_read_rec( const mrec_t** mrec, /*!< out: pointer to merge record, or NULL on end of list (non-NULL on I/O error) */ - ulint* offsets);/*!< out: offsets of mrec */ + ulint* offsets)/*!< out: offsets of mrec */ + __attribute__((nonnull, warn_unused_result)); #endif /* row0merge.h */ |