diff options
Diffstat (limited to 'storage/innobase/handler/ha_innopart.h')
-rw-r--r-- | storage/innobase/handler/ha_innopart.h | 1330 |
1 files changed, 1330 insertions, 0 deletions
diff --git a/storage/innobase/handler/ha_innopart.h b/storage/innobase/handler/ha_innopart.h new file mode 100644 index 00000000000..0a6bfe0b2f1 --- /dev/null +++ b/storage/innobase/handler/ha_innopart.h @@ -0,0 +1,1330 @@ +/***************************************************************************** + +Copyright (c) 2014, 2015, 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 +Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + +*****************************************************************************/ + +/* The InnoDB Partition handler: the interface between MySQL and InnoDB. */ + +#ifndef ha_innopart_h +#define ha_innopart_h + +/* JAN: TODO: MySQL 5.7 */ +//#include "partitioning/partition_handler.h" +#include "ha_partition.h" + +/* Forward declarations */ +class Altered_partitions; +class partition_info; + +/** HA_DUPLICATE_POS and HA_READ_BEFORE_WRITE_REMOVAL is not +set from ha_innobase, but cannot yet be supported in ha_innopart. +Full text and geometry is not yet supported. */ +const handler::Table_flags HA_INNOPART_DISABLED_TABLE_FLAGS = + ( HA_CAN_FULLTEXT + | HA_CAN_FULLTEXT_EXT + | HA_CAN_GEOMETRY + | HA_DUPLICATE_POS + | HA_READ_BEFORE_WRITE_REMOVAL); + +/** InnoDB partition specific Handler_share. */ +class Ha_innopart_share : public Partition_share +{ +private: + /** Array of all included table definitions (one per partition). */ + dict_table_t** m_table_parts; + + /** Instead of INNOBASE_SHARE::idx_trans_tbl. Maps MySQL index number + to InnoDB index per partition. */ + dict_index_t** m_index_mapping; + + /** Total number of partitions. */ + uint m_tot_parts; + + /** Number of indexes. */ + uint m_index_count; + + /** Reference count. */ + uint m_ref_count; + + /** Pointer back to owning TABLE_SHARE. */ + TABLE_SHARE* m_table_share; + + /** Virtual column template */ + innodb_col_templ_t* m_s_templ; +public: + Ha_innopart_share( + TABLE_SHARE* table_share); + + ~Ha_innopart_share(); + + /** Set innodb table for given partition. + @param[in] part_id Partition number. + @param[in] table Table. */ + inline + void + set_table_part( + uint part_id, + dict_table_t* table) + { + ut_ad(m_table_parts != NULL); + ut_ad(part_id < m_tot_parts); + m_table_parts[part_id] = table; + } + + /** Return innodb table for given partition. + @param[in] part_id Partition number. + @return InnoDB table. */ + inline + dict_table_t* + get_table_part( + uint part_id) const + { + ut_ad(m_table_parts != NULL); + ut_ad(part_id < m_tot_parts); + return(m_table_parts[part_id]); + } + + /** Return innodb index for given partition and key number. + @param[in] part_id Partition number. + @param[in] keynr Key number. + @return InnoDB index. */ + dict_index_t* + get_index( + uint part_id, + uint keynr); + + /** Get MySQL key number corresponding to InnoDB index. + @param[in] part_id Partition number. + @param[in] index InnoDB index. + @return MySQL key number or MAX_KEY if non-existent. */ + uint + get_mysql_key( + uint part_id, + const dict_index_t* index); + + /** Initialize the share with table and indexes per partition. + @param[in] part_info Partition info (partition names to use) + @param[in] table_name Table name (db/table_name) + @return false on success else true. */ + bool + open_table_parts( + partition_info* part_info, + const char* table_name); + + /** Close the table partitions. + If all instances are closed, also release the resources. */ + void + close_table_parts(); + + /* Static helper functions. */ + /** Fold to lower case if windows or lower_case_table_names == 1. + @param[in,out] s String to fold.*/ + static + void + partition_name_casedn_str( + char* s); + + /** Translate and append partition name. + @param[out] to String to write in filesystem charset + @param[in] from Name in system charset + @param[in] sep Separator + @param[in] len Max length of to buffer + @return length of written string. */ + static + size_t + append_sep_and_name( + char* to, + const char* from, + const char* sep, + size_t len); + + /** Set up the virtual column template for partition table, and points + all m_table_parts[]->vc_templ to it. + @param[in] table MySQL TABLE object + @param[in] ib_table InnoDB dict_table_t + @param[in] table_name Table name (db/table_name) */ + void + set_v_templ( + TABLE* table, + dict_table_t* ib_table, + const char* name); + +private: + /** Disable default constructor. */ + Ha_innopart_share() {}; + + /** Open one partition (lower lever innodb table). + @param[in] part_id Partition to open. + @param[in] partition_name Name of partition. + @return false on success else true. */ + bool + open_one_table_part( + uint part_id, + const char* partition_name); +}; + +/** The class defining a partitioning aware handle to an InnoDB table. +Based on ha_innobase and extended with +- Partition_helper for re-using common partitioning functionality +- Partition_handler for providing partitioning specific api calls. +Generic partitioning functions are implemented in Partition_helper. +Lower level storage functions are implemented in ha_innobase. +Partition_handler is inherited for implementing the handler level interface +for partitioning specific functions, like change_partitions and +truncate_partition. +InnoDB specific functions related to partitioning is implemented here. */ +class ha_innopart: + public ha_innobase, +// public Partition_helper, + public Partition_handler +{ +public: + ha_innopart( + handlerton* hton, + TABLE_SHARE* table_arg); + + ~ha_innopart(); + + /** Clone this handler, used when needing more than one cursor + to the same table. + @param[in] name Table name. + @param[in] mem_root mem_root to allocate from. + @retval Pointer to clone or NULL if error. */ + handler* + clone( + const char* name, + MEM_ROOT* mem_root); + + /** Check and register a table in the query cache. + Ask InnoDB if a query to a table can be cached. + @param[in] thd User thread handle. + @param[in] table_key Normalized path to the table. + @param[in] key_length Lenght of table_key. + @param[out] call_back Function pointer for checking if data + has changed. + @param[in,out] engine_data Data for call_back (not used). + @return TRUE if query caching of the table is permitted. */ + my_bool + register_query_cache_table( + THD* thd, + char* table_key, + size_t key_length, + qc_engine_callback* call_back, + ulonglong* engine_data) + { + /* Currently this would need to go through every + [sub] partition in the table to see if any of them has changed. + See row_search_check_if_query_cache_permitted(). + So disabled until we can avoid check all partitions. */ + return(FALSE); + } + + /** On-line ALTER TABLE interface @see handler0alter.cc @{ */ + + /** Check if InnoDB supports a particular alter table in-place. + @param[in] altered_table TABLE object for new version of table. + @param[in,out] ha_alter_info Structure describing changes to be done + by ALTER TABLE and holding data used during in-place alter. + @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported + @retval HA_ALTER_INPLACE_NO_LOCK Supported + @retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE Supported, but + requires lock during main phase and exclusive lock during prepare + phase. + @retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE Supported, prepare + phase requires exclusive lock. */ + enum_alter_inplace_result + check_if_supported_inplace_alter( + TABLE* altered_table, + Alter_inplace_info* ha_alter_info); + + /** Prepare in-place ALTER for table. + Allows InnoDB to update internal structures with concurrent + writes blocked (provided that check_if_supported_inplace_alter() + did not return HA_ALTER_INPLACE_NO_LOCK). + This will be invoked before inplace_alter_table(). + @param[in] altered_table TABLE object for new version of table. + @param[in,out] ha_alter_info Structure describing changes to be done + by ALTER TABLE and holding data used during in-place alter. + @retval true Failure. + @retval false Success. */ + bool + prepare_inplace_alter_table( + TABLE* altered_table, + Alter_inplace_info* ha_alter_info); + + /** Alter the table structure in-place. + Alter the table structure in-place with operations + specified using HA_ALTER_FLAGS and Alter_inplace_information. + The level of concurrency allowed during this operation depends + on the return value from check_if_supported_inplace_alter(). + @param[in] altered_table TABLE object for new version of table. + @param[in,out] ha_alter_info Structure describing changes to be done + by ALTER TABLE and holding data used during in-place alter. + @retval true Failure. + @retval false Success. */ + bool + inplace_alter_table( + TABLE* altered_table, + Alter_inplace_info* ha_alter_info); + + /** Commit or rollback. + Commit or rollback the changes made during + prepare_inplace_alter_table() and inplace_alter_table() inside + the storage engine. Note that the allowed level of concurrency + during this operation will be the same as for + inplace_alter_table() and thus might be higher than during + prepare_inplace_alter_table(). (E.g concurrent writes were + blocked during prepare, but might not be during commit). + @param[in] altered_table TABLE object for new version of table. + @param[in] ha_alter_info Structure describing changes to be done + by ALTER TABLE and holding data used during in-place alter. + @param[in,out] commit true => Commit, false => Rollback. + @retval true Failure. + @retval false Success. */ + bool + commit_inplace_alter_table( + TABLE* altered_table, + Alter_inplace_info* ha_alter_info, + bool commit); + + /** Notify the storage engine that the table structure (.frm) has + been updated. + + ha_partition allows inplace operations that also upgrades the engine + if it supports partitioning natively. So if this is the case then + we will remove the .par file since it is not used with ha_innopart + (we use the internal data dictionary instead). */ + void + notify_table_changed(); + /** @} */ + + // TODO: should we implement init_table_handle_for_HANDLER() ? + // (or is sql_stat_start handled correctly anyway?) + int + optimize( + THD* thd, + HA_CHECK_OPT* check_opt); + + int + discard_or_import_tablespace( + my_bool discard); + + /** Compare key and rowid. + Helper function for sorting records in the priority queue. + a/b points to table->record[0] rows which must have the + key fields set. The bytes before a and b store the rowid. + This is used for comparing/sorting rows first according to + KEY and if same KEY, by rowid (ref). + + @param[in] key_info Null terminated array of index + information. + @param[in] a Pointer to record+ref in first record. + @param[in] b Pointer to record+ref in second record. + @return Return value is SIGN(first_rec - second_rec) + @retval 0 Keys are equal. + @retval -1 second_rec is greater than first_rec. + @retval +1 first_rec is greater than second_rec. */ + static + int + key_and_rowid_cmp( + KEY** key_info, + uchar *a, + uchar *b); + + int + extra( + enum ha_extra_function operation); + + void + print_error( + int error, + myf errflag); + + bool + is_ignorable_error( + int error); + + int + start_stmt( + THD* thd, + thr_lock_type lock_type); + + ha_rows + records_in_range( + uint inx, + key_range* min_key, + key_range* max_key); + + ha_rows + estimate_rows_upper_bound(); + + uint + alter_table_flags( + uint flags); + + void + update_create_info( + HA_CREATE_INFO* create_info); + + int + create( + const char* name, + TABLE* form, + HA_CREATE_INFO* create_info); + + int + truncate(); + + int + check( + THD* thd, + HA_CHECK_OPT* check_opt); + + /** Repair table. + Will only handle records in wrong partition, not repairing + corrupt innodb indexes. + @param[in] thd Thread context. + @param[in] repair_opt Repair options. + @return 0 or error code. */ + int + repair( + THD* thd, + HA_CHECK_OPT* repair_opt); + + bool + can_switch_engines(); + + uint + referenced_by_foreign_key(); + + void + get_auto_increment( + ulonglong offset, + ulonglong increment, + ulonglong nb_desired_values, + ulonglong* first_value, + ulonglong* nb_reserved_values); + + int + cmp_ref( + const uchar* ref1, + const uchar* ref2); + + int + read_range_first( + const key_range* start_key, + const key_range* end_key, + bool eq_range_arg, + bool sorted) + { + return(Partition_helper::ph_read_range_first( + start_key, + end_key, + eq_range_arg, + sorted)); + } + + void + position( + const uchar* record) + { + Partition_helper::ph_position(record); + } + + int + rnd_pos_by_record( + uchar* record) + { + return(Partition_helper::ph_rnd_pos_by_record(record)); + } + + /* TODO: Implement these! */ + bool + check_if_incompatible_data( + HA_CREATE_INFO* info, + uint table_changes) + { + ut_ad(0); + return(COMPATIBLE_DATA_NO); + } + + int + delete_all_rows() + { + return(handler::delete_all_rows()); + } + + int + disable_indexes( + uint mode) + { + return(HA_ERR_WRONG_COMMAND); + } + + int + enable_indexes( + uint mode) + { + return(HA_ERR_WRONG_COMMAND); + } + + void + free_foreign_key_create_info( + char* str) + { + ut_ad(0); + } + + int + ft_init() + { + ut_ad(0); + return(HA_ERR_WRONG_COMMAND); + } + + FT_INFO* + ft_init_ext( + uint flags, + uint inx, + String* key) + { + ut_ad(0); + return(NULL); + } + + FT_INFO* + ft_init_ext_with_hints( + uint inx, + String* key, + /* JAN: TODO: MySQL 5. / + Ft_hints* hints)*/ + void* hints) + { + ut_ad(0); + return(NULL); + } + + int + ft_read( + uchar* buf) + { + ut_ad(0); + return(HA_ERR_WRONG_COMMAND); + } + + bool + get_foreign_dup_key( + char* child_table_name, + uint child_table_name_len, + char* child_key_name, + uint child_key_name_len) + { + ut_ad(0); + return(false); + } + + // TODO: not yet supporting FK. + char* + get_foreign_key_create_info() + { + return(NULL); + } + + // TODO: not yet supporting FK. + int + get_foreign_key_list( + THD* thd, + List<FOREIGN_KEY_INFO>* f_key_list) + { + return(0); + } + + // TODO: not yet supporting FK. + int + get_parent_foreign_key_list( + THD* thd, + List<FOREIGN_KEY_INFO>* f_key_list) + { + return(0); + } + + // TODO: not yet supporting FK. + int + get_cascade_foreign_key_table_list( + THD* thd, + List<st_handler_tablename>* fk_table_list) + { + return(0); + } + + int + read_range_next() + { + return(Partition_helper::ph_read_range_next()); + } + + uint32 + calculate_key_hash_value( + Field** field_array) + { + return(Partition_helper::ph_calculate_key_hash_value(field_array)); + } + + Table_flags + table_flags() const + { + return(ha_innobase::table_flags() | HA_CAN_REPAIR); + } + + void + release_auto_increment() + { + Partition_helper::ph_release_auto_increment(); + } + + /** Implementing Partition_handler interface @see partition_handler.h + @{ */ + + /** See Partition_handler. */ + void + get_dynamic_partition_info( + ha_statistics* stat_info, + ha_checksum* check_sum, + uint part_id) + { + Partition_helper::get_dynamic_partition_info_low( + stat_info, + check_sum, + part_id); + } + + uint + alter_flags( + uint flags __attribute__((unused))) const + { + return(HA_PARTITION_FUNCTION_SUPPORTED + | HA_FAST_CHANGE_PARTITION); + } + + Partition_handler* + get_partition_handler() + { + return(static_cast<Partition_handler*>(this)); + } + + void + set_part_info( + partition_info* part_info, + bool early) + { + Partition_helper::set_part_info_low(part_info, early); + } + + void + initialize_partitioning( + partition_info* part_info, + bool early) + { + Partition_helper::set_part_info_low(part_info, early); + } + + handler* + get_handler() + { + return(static_cast<handler*>(this)); + } + /** @} */ + +private: + /** Pointer to Ha_innopart_share on the TABLE_SHARE. */ + Ha_innopart_share* m_part_share; + + /** ins_node per partition. Synchronized with prebuilt->ins_node + when changing partitions. */ + ins_node_t** m_ins_node_parts; + + /** upd_node per partition. Synchronized with prebuilt->upd_node + when changing partitions. */ + upd_node_t** m_upd_node_parts; + + /** blob_heap per partition. Synchronized with prebuilt->blob_heap + when changing partitions. */ + mem_heap_t** m_blob_heap_parts; + + /** trx_id from the partitions table->def_trx_id. Keep in sync + with prebuilt->trx_id when changing partitions. + prebuilt only reflects the current partition! */ + trx_id_t* m_trx_id_parts; + + /** row_read_type per partition. */ + ulint* m_row_read_type_parts; + + /** sql_stat_start per partition. */ + uchar* m_sql_stat_start_parts; + + /** persistent cursors per partition. */ + btr_pcur_t* m_pcur_parts; + + /** persistent cluster cursors per partition. */ + btr_pcur_t* m_clust_pcur_parts; + + /** map from part_id to offset in above two arrays. */ + uint16_t* m_pcur_map; + + /** Original m_prebuilt->pcur. */ + btr_pcur_t* m_pcur; + + /** Original m_prebuilt->clust_pcur. */ + btr_pcur_t* m_clust_pcur; + + /** New partitions during ADD/REORG/... PARTITION. */ + Altered_partitions* m_new_partitions; + + /** Clear used ins_nodes and upd_nodes. */ + void + clear_ins_upd_nodes(); + + /** Clear the blob heaps for all partitions */ + void + clear_blob_heaps(); + + /** Reset state of file to after 'open'. This function is called + after every statement for all tables used by that statement. */ + int + reset(); + + /** Allocate the array to hold blob heaps for all partitions */ + mem_heap_t** + alloc_blob_heap_array(); + + /** Free the array that holds blob heaps for all partitions */ + void + free_blob_heap_array(); + + /** Changes the active index of a handle. + @param[in] part_id Use this partition. + @param[in] keynr Use this index; MAX_KEY means always + clustered index, even if it was internally generated by InnoDB. + @return 0 or error code. */ + int + change_active_index( + uint part_id, + uint keynr); + + /** Move to next partition and set its index. + @return 0 for success else error number. */ + int + next_partition_index(); + + /** Internally called for initializing auto increment value. + Should never be called, but defined to catch such errors. + @return 0 on success else error code. */ + int + innobase_initialize_autoinc(); + + /** Get the index for the current partition + @param[in] keynr MySQL index number. + @return InnoDB index or NULL. */ + dict_index_t* + innobase_get_index( + uint keynr); + + /** Get the index for a handle. + Does not change active index. + @param[in] keynr use this index; MAX_KEY means always clustered + index, even if it was internally generated by InnoDB. + @param[in] part_id From this partition. + @return NULL or index instance. */ + dict_index_t* + innopart_get_index( + uint part_id, + uint keynr); + + /** Change active partition. + Copies needed info into m_prebuilt from the partition specific memory. + @param[in] part_id Partition to set as active. */ + void + set_partition( + uint part_id); + + /** Update active partition. + Copies needed info from m_prebuilt into the partition specific memory. + @param[in] part_id Partition to set as active. */ + void + update_partition( + uint part_id); + + /** Helpers needed by Partition_helper, @see partition_handler.h @{ */ + + /** Set the autoinc column max value. + This should only be called once from ha_innobase::open(). + Therefore there's no need for a covering lock. + @param[in] no_lock If locking should be skipped. Not used! + @return 0 on success else error code. */ + int + initialize_auto_increment( + bool /* no_lock */); + + /** Save currently highest auto increment value. + @param[in] nr Auto increment value to save. */ + void + save_auto_increment( + ulonglong nr); + + /** Setup the ordered record buffer and the priority queue. + @param[in] used_parts Number of used partitions in query. + @return false for success, else true. */ + int + init_record_priority_queue_for_parts( + uint used_parts); + + /** Destroy the ordered record buffer and the priority queue. */ + void + destroy_record_priority_queue_for_parts(); + + /** Prepare for creating new partitions during ALTER TABLE ... + PARTITION. + @param[in] num_partitions Number of new partitions to be created. + @param[in] only_create True if only creating the partition + (no open/lock is needed). + @return 0 for success else error code. */ + int + prepare_for_new_partitions( + uint num_partitions, + bool only_create); + + /** Create a new partition to be filled during ALTER TABLE ... + PARTITION. + @param[in] table Table to create the partition in. + @param[in] create_info Table/partition specific create info. + @param[in] part_name Partition name. + @param[in] new_part_id Partition id in new table. + @param[in] part_elem Partition element. + @return 0 for success else error code. */ + int + create_new_partition( + TABLE* table, + HA_CREATE_INFO* create_info, + const char* part_name, + uint new_part_id, + partition_element* part_elem); + + /** Close and finalize new partitions. */ + void + close_new_partitions(); + + /** write row to new partition. + @param[in] new_part New partition to write to. + @return 0 for success else error code. */ + int + write_row_in_new_part( + uint new_part); + + /** Write a row in specific partition. + Stores a row in an InnoDB database, to the table specified in this + handle. + @param[in] part_id Partition to write to. + @param[in] row A row in MySQL format. + @return error code. */ + int + write_row_in_part( + uint part_id, + uchar* row); + + /** Update a row in partition. + Updates a row given as a parameter to a new value. + @param[in] part_id Partition to update row in. + @param[in] old_row Old row in MySQL format. + @param[in] new_row New row in MySQL format. + @return error number or 0. */ + int + update_row_in_part( + uint part_id, + const uchar* old_row, + uchar* new_row); + + /** Deletes a row in partition. + @param[in] part_id Partition to delete from. + @param[in] row Row to delete in MySQL format. + @return error number or 0. */ + int + delete_row_in_part( + uint part_id, + const uchar* row); + + /** Return first record in index from a partition. + @param[in] part Partition to read from. + @param[out] record First record in index in the partition. + @return error number or 0. */ + int + index_first_in_part( + uint part, + uchar* record); + + /** Return last record in index from a partition. + @param[in] part Partition to read from. + @param[out] record Last record in index in the partition. + @return error number or 0. */ + int + index_last_in_part( + uint part, + uchar* record); + + /** Return previous record in index from a partition. + @param[in] part Partition to read from. + @param[out] record Last record in index in the partition. + @return error number or 0. */ + int + index_prev_in_part( + uint part, + uchar* record); + + /** Return next record in index from a partition. + @param[in] part Partition to read from. + @param[out] record Last record in index in the partition. + @return error number or 0. */ + int + index_next_in_part( + uint part, + uchar* record); + + /** Return next same record in index from a partition. + This routine is used to read the next record, but only if the key is + the same as supplied in the call. + @param[in] part Partition to read from. + @param[out] record Last record in index in the partition. + @param[in] key Key to match. + @param[in] length Length of key. + @return error number or 0. */ + int + index_next_same_in_part( + uint part, + uchar* record, + const uchar* key, + uint length); + + /** Start index scan and return first record from a partition. + This routine starts an index scan using a start key. The calling + function will check the end key on its own. + @param[in] part Partition to read from. + @param[out] record First matching record in index in the partition. + @param[in] key Key to match. + @param[in] keypart_map Which part of the key to use. + @param[in] find_flag Key condition/direction to use. + @return error number or 0. */ + int + index_read_map_in_part( + uint part, + uchar* record, + const uchar* key, + key_part_map keypart_map, + enum ha_rkey_function find_flag); + + /** Return last matching record in index from a partition. + @param[in] part Partition to read from. + @param[out] record Last matching record in index in the partition. + @param[in] key Key to match. + @param[in] keypart_map Which part of the key to use. + @return error number or 0. */ + int + index_read_last_map_in_part( + uint part, + uchar* record, + const uchar* key, + key_part_map keypart_map); + + /** Start index scan and return first record from a partition. + This routine starts an index scan using a start and end key. + @param[in] part Partition to read from. + @param[out] record First matching record in index in the partition. + if NULL use table->record[0] as return buffer. + @param[in] start_key Start key to match. + @param[in] end_key End key to match. + @param[in] eq_range Is equal range, start_key == end_key. + @param[in] sorted Return rows in sorted order. + @return error number or 0. */ + int + read_range_first_in_part( + uint part, + uchar* record, + const key_range* start_key, + const key_range* end_key, + bool eq_range, + bool sorted); + + /** Return next record in index range scan from a partition. + @param[in] part Partition to read from. + @param[out] record First matching record in index in the partition. + if NULL use table->record[0] as return buffer. + @return error number or 0. */ + int + read_range_next_in_part( + uint part, + uchar* record); + + /** Start index scan and return first record from a partition. + This routine starts an index scan using a start key. The calling + function will check the end key on its own. + @param[in] part Partition to read from. + @param[out] record First matching record in index in the partition. + @param[in] index Index to read from. + @param[in] key Key to match. + @param[in] keypart_map Which part of the key to use. + @param[in] find_flag Key condition/direction to use. + @return error number or 0. */ + int + index_read_idx_map_in_part( + uint part, + uchar* record, + uint index, + const uchar* key, + key_part_map keypart_map, + enum ha_rkey_function find_flag); + + /** Initialize random read/scan of a specific partition. + @param[in] part_id Partition to initialize. + @param[in] table_scan True for scan else random access. + @return error number or 0. */ + int + rnd_init_in_part( + uint part_id, + bool table_scan); + + /** Get next row during scan of a specific partition. + @param[in] part_id Partition to read from. + @param[out] record Next row. + @return error number or 0. */ + int + rnd_next_in_part( + uint part_id, + uchar* record); + + /** End random read/scan of a specific partition. + @param[in] part_id Partition to end random read/scan. + @param[in] table_scan True for scan else random access. + @return error number or 0. */ + int + rnd_end_in_part( + uint part_id, + bool table_scan); + + /** Get a reference to the current cursor position in the last used + partition. + @param[out] ref Reference (PK if exists else row_id). + @param[in] record Record to position. */ + void + position_in_last_part( + uchar* ref, + const uchar* record); + + /** Read record by given record (by its PK) from the last used partition. + see handler::rnd_pos_by_record(). + @param[in,out] record Record to position. + @return 0 or error number. */ + int + rnd_pos_by_record_in_last_part( + uchar* record) + { + /* Not much overhead to use default function. + This avoids out-of-sync code. */ + return(handler::rnd_pos_by_record(record)); + } + + /** Copy a cached MySQL record. + @param[out] to_record Where to copy the MySQL record. + @param[in] from_record Which record to copy. */ + void + copy_cached_row( + uchar* to_record, + const uchar* from_record); + /** @} */ + + /* Private handler:: functions specific for native InnoDB partitioning. + @see handler.h @{ */ + + int + open( + const char* name, + int mode, + uint test_if_locked); + + int + close(); + + double + scan_time(); + + /** Was the last returned row semi consistent read. + In an UPDATE or DELETE, if the row under the cursor was locked by + another transaction, and the engine used an optimistic read of the last + committed row value under the cursor, then the engine returns 1 from + this function. MySQL must NOT try to update this optimistic value. If + the optimistic value does not match the WHERE condition, MySQL can + decide to skip over this row. This can be used to avoid unnecessary + lock waits. + + If this method returns true, it will also signal the storage + engine that the next read will be a locking re-read of the row. + @see handler.h and row0mysql.h + @return true if last read was semi consistent else false. */ + bool was_semi_consistent_read(); + + /** Try semi consistent read. + Tell the engine whether it should avoid unnecessary lock waits. + If yes, in an UPDATE or DELETE, if the row under the cursor was locked + by another transaction, the engine may try an optimistic read of + the last committed row value under the cursor. + @see handler.h and row0mysql.h + @param[in] yes Should semi-consistent read be used. */ + void try_semi_consistent_read( + bool yes); + + /** Removes a lock on a row. + Removes a new lock set on a row, if it was not read optimistically. + This can be called after a row has been read in the processing of + an UPDATE or a DELETE query. @see ha_innobase::unlock_row(). */ + void unlock_row(); + + int + index_init( + uint index, + bool sorted); + + int + index_end(); + + int + rnd_init( + bool scan) + { + return(Partition_helper::ph_rnd_init(scan)); + } + + int + rnd_end() + { + return(Partition_helper::ph_rnd_end()); + } + + int + external_lock( + THD* thd, + int lock_type); + + int + write_row( + uchar* record) + { + return(Partition_helper::ph_write_row(record)); + } + + int + update_row( + const uchar* old_record, + uchar* new_record) + { + return(Partition_helper::ph_update_row(old_record, new_record)); + } + + int + delete_row( + const uchar* record) + { + return(Partition_helper::ph_delete_row(record)); + } + /** @} */ + + /** Truncate partition. + Called from Partition_handler::trunctate_partition(). */ + int + truncate_partition_low(); + + /** Change partitions according to ALTER TABLE ... PARTITION ... + Called from Partition_handler::change_partitions(). + @param[in] create_info Table create info. + @param[in] path Path including db/table_name. + @param[out] copied Number of copied rows. + @param[out] deleted Number of deleted rows. + @return 0 for success or error code. */ + int + change_partitions_low( + HA_CREATE_INFO* create_info, + const char* path, + ulonglong* const copied, + ulonglong* const deleted) + { + return(Partition_helper::change_partitions( + create_info, + path, + copied, + deleted)); + } + + /** Access methods to protected areas in handler to avoid adding + friend class Partition_helper in class handler. + @see partition_handler.h @{ */ + + THD* + get_thd() const + { + return ha_thd(); + } + + TABLE* + get_table() const + { + return table; + } + + bool + get_eq_range() const + { + return eq_range; + } + + void + set_eq_range(bool eq_range_arg) + { + eq_range= eq_range_arg; + } + + void + set_range_key_part(KEY_PART_INFO *key_part) + { + range_key_part= key_part; + } + /** @} */ + + /** Fill in data_dir_path and tablespace name from internal data + dictionary. + @param part_elem Partition element to fill. + @param ib_table InnoDB table to copy from. */ + void + update_part_elem( + partition_element* part_elem, + dict_table_t* ib_table); +protected: + /* Protected handler:: functions specific for native InnoDB partitioning. + @see handler.h @{ */ + + int + rnd_next( + uchar* record) + { + return(Partition_helper::ph_rnd_next(record)); + } + + int + rnd_pos( + uchar* record, + uchar* pos); + + int + records( + ha_rows* num_rows); + + int + index_next( + uchar* record) + { + return(Partition_helper::ph_index_next(record)); + } + + int + index_next_same( + uchar* record, + const uchar* key, + uint keylen) + { + return(Partition_helper::ph_index_next_same(record, key, keylen)); + } + + int + index_prev( + uchar* record) + { + return(Partition_helper::ph_index_prev(record)); + } + + int + index_first( + uchar* record) + { + return(Partition_helper::ph_index_first(record)); + } + + int + index_last( + uchar* record) + { + return(Partition_helper::ph_index_last(record)); + } + + int + index_read_last_map( + uchar* record, + const uchar* key, + key_part_map keypart_map) + { + return(Partition_helper::ph_index_read_last_map( + record, + key, + keypart_map)); + } + + int + index_read_map( + uchar* buf, + const uchar* key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) + { + return(Partition_helper::ph_index_read_map( + buf, + key, + keypart_map, + find_flag)); + } + + int + index_read_idx_map( + uchar* buf, + uint index, + const uchar* key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) + { + return(Partition_helper::ph_index_read_idx_map( + buf, + index, + key, + keypart_map, + find_flag)); + } + /** @} */ + + /** Updates and return statistics. + Returns statistics information of the table to the MySQL interpreter, + in various fields of the handle object. + @param[in] flag Flags for what to update and return. + @param[in] is_analyze True if called from ::analyze(). + @return HA_ERR_* error code or 0. */ + int + info_low( + uint flag, + bool is_analyze); +}; +#endif /* ha_innopart_h */ |