1 /***************************************************************************** 2 3 Copyright (c) 2014, 2019, Oracle and/or its affiliates. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License, version 2.0, 7 as published by the Free Software Foundation. 8 9 This program is also distributed with certain software (including 10 but not limited to OpenSSL) that is licensed under separate terms, 11 as designated in a particular file or component or in included license 12 documentation. The authors of MySQL hereby grant you an additional 13 permission to link the program and your derivative works with the 14 separately licensed software that they have included with MySQL. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License, version 2.0, for more details. 20 21 You should have received a copy of the GNU General Public License along with 22 this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25 *****************************************************************************/ 26 27 /* The InnoDB Partition handler: the interface between MySQL and InnoDB. */ 28 29 #ifndef ha_innopart_h 30 #define ha_innopart_h 31 32 #include "partitioning/partition_handler.h" 33 34 /* Forward declarations */ 35 class Altered_partitions; 36 class partition_info; 37 38 /** HA_DUPLICATE_POS and HA_READ_BEFORE_WRITE_REMOVAL is not 39 set from ha_innobase, but cannot yet be supported in ha_innopart. 40 Full text and geometry is not yet supported. */ 41 const handler::Table_flags HA_INNOPART_DISABLED_TABLE_FLAGS = 42 ( HA_CAN_FULLTEXT 43 | HA_CAN_FULLTEXT_EXT 44 | HA_CAN_GEOMETRY 45 | HA_DUPLICATE_POS 46 | HA_READ_BEFORE_WRITE_REMOVAL); 47 48 /** InnoDB partition specific Handler_share. */ 49 class Ha_innopart_share : public Partition_share 50 { 51 private: 52 /** Array of all included table definitions (one per partition). */ 53 dict_table_t** m_table_parts; 54 55 /** Instead of INNOBASE_SHARE::idx_trans_tbl. Maps MySQL index number 56 to InnoDB index per partition. */ 57 dict_index_t** m_index_mapping; 58 59 /** Total number of partitions. */ 60 uint m_tot_parts; 61 62 /** Number of indexes. */ 63 uint m_index_count; 64 65 /** Reference count. */ 66 uint m_ref_count; 67 68 /** Pointer back to owning TABLE_SHARE. */ 69 TABLE_SHARE* m_table_share; 70 71 public: 72 Ha_innopart_share( 73 TABLE_SHARE* table_share); 74 75 ~Ha_innopart_share(); 76 77 /** Set innodb table for given partition. 78 @param[in] part_id Partition number. 79 @param[in] table Table. */ 80 inline 81 void set_table_part(uint part_id,dict_table_t * table)82 set_table_part( 83 uint part_id, 84 dict_table_t* table) 85 { 86 ut_ad(m_table_parts != NULL); 87 ut_ad(part_id < m_tot_parts); 88 m_table_parts[part_id] = table; 89 } 90 91 /** Return innodb table for given partition. 92 @param[in] part_id Partition number. 93 @return InnoDB table. */ 94 inline 95 dict_table_t* get_table_part(uint part_id)96 get_table_part( 97 uint part_id) const 98 { 99 ut_ad(m_table_parts != NULL); 100 ut_ad(part_id < m_tot_parts); 101 return(m_table_parts[part_id]); 102 } 103 104 /** Return innodb index for given partition and key number. 105 @param[in] part_id Partition number. 106 @param[in] keynr Key number. 107 @return InnoDB index. */ 108 dict_index_t* 109 get_index( 110 uint part_id, 111 uint keynr); 112 113 /** Get MySQL key number corresponding to InnoDB index. 114 @param[in] part_id Partition number. 115 @param[in] index InnoDB index. 116 @return MySQL key number or MAX_KEY if non-existent. */ 117 uint 118 get_mysql_key( 119 uint part_id, 120 const dict_index_t* index); 121 122 /** Initialize the share with table and indexes per partition. 123 @param[in] part_info Partition info (partition names to use) 124 @param[in] table_name Table name (db/table_name) 125 @return false on success else true. */ 126 bool 127 open_table_parts( 128 partition_info* part_info, 129 const char* table_name); 130 131 /** Close the table partitions. 132 If all instances are closed, also release the resources. */ 133 void 134 close_table_parts(); 135 136 /* Static helper functions. */ 137 /** Fold to lower case if windows or lower_case_table_names == 1. 138 @param[in,out] s String to fold.*/ 139 static 140 void 141 partition_name_casedn_str( 142 char* s); 143 144 /** Translate and append partition name. 145 @param[out] to String to write in filesystem charset 146 @param[in] from Name in system charset 147 @param[in] sep Separator 148 @param[in] len Max length of to buffer 149 @return length of written string. */ 150 static 151 size_t 152 append_sep_and_name( 153 char* to, 154 const char* from, 155 const char* sep, 156 size_t len); 157 158 /** Set up the virtual column template for partition table, and points 159 all m_table_parts[]->vc_templ to it. 160 @param[in] table MySQL TABLE object 161 @param[in] ib_table InnoDB dict_table_t 162 @param[in] table_name Table name (db/table_name) */ 163 void 164 set_v_templ( 165 TABLE* table, 166 dict_table_t* ib_table, 167 const char* name); 168 169 private: 170 /** Disable default constructor. */ Ha_innopart_share()171 Ha_innopart_share() {}; 172 173 /** Open one partition (lower lever innodb table). 174 @param[in] part_id Partition to open. 175 @param[in] partition_name Name of partition. 176 @return false on success else true. */ 177 bool 178 open_one_table_part( 179 uint part_id, 180 const char* partition_name); 181 }; 182 183 /** The class defining a partitioning aware handle to an InnoDB table. 184 Based on ha_innobase and extended with 185 - Partition_helper for re-using common partitioning functionality 186 - Partition_handler for providing partitioning specific api calls. 187 Generic partitioning functions are implemented in Partition_helper. 188 Lower level storage functions are implemented in ha_innobase. 189 Partition_handler is inherited for implementing the handler level interface 190 for partitioning specific functions, like change_partitions and 191 truncate_partition. 192 InnoDB specific functions related to partitioning is implemented here. */ 193 class ha_innopart: 194 public ha_innobase, 195 public Partition_helper, 196 public Partition_handler 197 { 198 public: 199 ha_innopart( 200 handlerton* hton, 201 TABLE_SHARE* table_arg); 202 203 ~ha_innopart(); 204 205 /** Clone this handler, used when needing more than one cursor 206 to the same table. 207 @param[in] name Table name. 208 @param[in] mem_root mem_root to allocate from. 209 @retval Pointer to clone or NULL if error. */ 210 handler* 211 clone( 212 const char* name, 213 MEM_ROOT* mem_root); 214 215 /** Check and register a table in the query cache. 216 Ask InnoDB if a query to a table can be cached. 217 @param[in] thd User thread handle. 218 @param[in] table_key Normalized path to the table. 219 @param[in] key_length Lenght of table_key. 220 @param[out] call_back Function pointer for checking if data 221 has changed. 222 @param[in,out] engine_data Data for call_back (not used). 223 @return TRUE if query caching of the table is permitted. */ 224 my_bool register_query_cache_table(THD * thd,char * table_key,size_t key_length,qc_engine_callback * call_back,ulonglong * engine_data)225 register_query_cache_table( 226 THD* thd, 227 char* table_key, 228 size_t key_length, 229 qc_engine_callback* call_back, 230 ulonglong* engine_data) 231 { 232 /* Currently this would need to go through every 233 [sub] partition in the table to see if any of them has changed. 234 See row_search_check_if_query_cache_permitted(). 235 So disabled until we can avoid check all partitions. */ 236 return(FALSE); 237 } 238 239 /** On-line ALTER TABLE interface @see handler0alter.cc @{ */ 240 241 /** Check if InnoDB supports a particular alter table in-place. 242 @param[in] altered_table TABLE object for new version of table. 243 @param[in,out] ha_alter_info Structure describing changes to be done 244 by ALTER TABLE and holding data used during in-place alter. 245 @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported 246 @retval HA_ALTER_INPLACE_NO_LOCK Supported 247 @retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE Supported, but 248 requires lock during main phase and exclusive lock during prepare 249 phase. 250 @retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE Supported, prepare 251 phase requires exclusive lock. */ 252 enum_alter_inplace_result 253 check_if_supported_inplace_alter( 254 TABLE* altered_table, 255 Alter_inplace_info* ha_alter_info); 256 257 /** Prepare in-place ALTER for table. 258 Allows InnoDB to update internal structures with concurrent 259 writes blocked (provided that check_if_supported_inplace_alter() 260 did not return HA_ALTER_INPLACE_NO_LOCK). 261 This will be invoked before inplace_alter_table(). 262 @param[in] altered_table TABLE object for new version of table. 263 @param[in,out] ha_alter_info Structure describing changes to be done 264 by ALTER TABLE and holding data used during in-place alter. 265 @retval true Failure. 266 @retval false Success. */ 267 bool 268 prepare_inplace_alter_table( 269 TABLE* altered_table, 270 Alter_inplace_info* ha_alter_info); 271 272 /** Alter the table structure in-place. 273 Alter the table structure in-place with operations 274 specified using HA_ALTER_FLAGS and Alter_inplace_information. 275 The level of concurrency allowed during this operation depends 276 on the return value from check_if_supported_inplace_alter(). 277 @param[in] altered_table TABLE object for new version of table. 278 @param[in,out] ha_alter_info Structure describing changes to be done 279 by ALTER TABLE and holding data used during in-place alter. 280 @retval true Failure. 281 @retval false Success. */ 282 bool 283 inplace_alter_table( 284 TABLE* altered_table, 285 Alter_inplace_info* ha_alter_info); 286 287 /** Commit or rollback. 288 Commit or rollback the changes made during 289 prepare_inplace_alter_table() and inplace_alter_table() inside 290 the storage engine. Note that the allowed level of concurrency 291 during this operation will be the same as for 292 inplace_alter_table() and thus might be higher than during 293 prepare_inplace_alter_table(). (E.g concurrent writes were 294 blocked during prepare, but might not be during commit). 295 @param[in] altered_table TABLE object for new version of table. 296 @param[in] ha_alter_info Structure describing changes to be done 297 by ALTER TABLE and holding data used during in-place alter. 298 @param[in,out] commit true => Commit, false => Rollback. 299 @retval true Failure. 300 @retval false Success. */ 301 bool 302 commit_inplace_alter_table( 303 TABLE* altered_table, 304 Alter_inplace_info* ha_alter_info, 305 bool commit); 306 307 /** Notify the storage engine that the table structure (.frm) has 308 been updated. 309 310 ha_partition allows inplace operations that also upgrades the engine 311 if it supports partitioning natively. So if this is the case then 312 we will remove the .par file since it is not used with ha_innopart 313 (we use the internal data dictionary instead). */ 314 void 315 notify_table_changed(); 316 /** @} */ 317 318 // TODO: should we implement init_table_handle_for_HANDLER() ? 319 // (or is sql_stat_start handled correctly anyway?) 320 int 321 optimize( 322 THD* thd, 323 HA_CHECK_OPT* check_opt); 324 325 int 326 discard_or_import_tablespace( 327 my_bool discard); 328 329 /** Compare key and rowid. 330 Helper function for sorting records in the priority queue. 331 a/b points to table->record[0] rows which must have the 332 key fields set. The bytes before a and b store the rowid. 333 This is used for comparing/sorting rows first according to 334 KEY and if same KEY, by rowid (ref). 335 336 @param[in] key_info Null terminated array of index 337 information. 338 @param[in] a Pointer to record+ref in first record. 339 @param[in] b Pointer to record+ref in second record. 340 @return Return value is SIGN(first_rec - second_rec) 341 @retval 0 Keys are equal. 342 @retval -1 second_rec is greater than first_rec. 343 @retval +1 first_rec is greater than second_rec. */ 344 static 345 int 346 key_and_rowid_cmp( 347 KEY** key_info, 348 uchar *a, 349 uchar *b); 350 351 int 352 extra( 353 enum ha_extra_function operation); 354 355 void 356 print_error( 357 int error, 358 myf errflag); 359 360 bool 361 is_ignorable_error( 362 int error); 363 364 int 365 start_stmt( 366 THD* thd, 367 thr_lock_type lock_type); 368 369 ha_rows 370 records_in_range( 371 uint inx, 372 key_range* min_key, 373 key_range* max_key); 374 375 ha_rows 376 estimate_rows_upper_bound(); 377 378 uint 379 alter_table_flags( 380 uint flags); 381 382 void 383 update_create_info( 384 HA_CREATE_INFO* create_info); 385 386 int 387 create( 388 const char* name, 389 TABLE* form, 390 HA_CREATE_INFO* create_info); 391 392 int 393 truncate(); 394 395 int 396 check( 397 THD* thd, 398 HA_CHECK_OPT* check_opt); 399 400 /** Repair table. 401 Will only handle records in wrong partition, not repairing 402 corrupt innodb indexes. 403 @param[in] thd Thread context. 404 @param[in] repair_opt Repair options. 405 @return 0 or error code. */ 406 int 407 repair( 408 THD* thd, 409 HA_CHECK_OPT* repair_opt); 410 411 bool 412 can_switch_engines(); 413 414 uint 415 referenced_by_foreign_key(); 416 417 void 418 get_auto_increment( 419 ulonglong offset, 420 ulonglong increment, 421 ulonglong nb_desired_values, 422 ulonglong* first_value, 423 ulonglong* nb_reserved_values); 424 425 426 /** Get partition row type 427 @param[in] Id of partition for which row type to be retrieved 428 @return Partition row type */ 429 enum row_type get_partition_row_type(uint part_id); 430 431 int 432 cmp_ref( 433 const uchar* ref1, 434 const uchar* ref2); 435 436 int read_range_first(const key_range * start_key,const key_range * end_key,bool eq_range_arg,bool sorted)437 read_range_first( 438 const key_range* start_key, 439 const key_range* end_key, 440 bool eq_range_arg, 441 bool sorted) 442 { 443 return(Partition_helper::ph_read_range_first( 444 start_key, 445 end_key, 446 eq_range_arg, 447 sorted)); 448 } 449 450 void position(const uchar * record)451 position( 452 const uchar* record) 453 { 454 Partition_helper::ph_position(record); 455 } 456 457 /* TODO: Implement these! */ 458 bool check_if_incompatible_data(HA_CREATE_INFO * info,uint table_changes)459 check_if_incompatible_data( 460 HA_CREATE_INFO* info, 461 uint table_changes) 462 { 463 ut_ad(0); 464 return(COMPATIBLE_DATA_NO); 465 } 466 467 int delete_all_rows()468 delete_all_rows() 469 { 470 return(handler::delete_all_rows()); 471 } 472 473 int disable_indexes(uint mode)474 disable_indexes( 475 uint mode) 476 { 477 return(HA_ERR_WRONG_COMMAND); 478 } 479 480 int enable_indexes(uint mode)481 enable_indexes( 482 uint mode) 483 { 484 return(HA_ERR_WRONG_COMMAND); 485 } 486 487 void free_foreign_key_create_info(char * str)488 free_foreign_key_create_info( 489 char* str) 490 { 491 ut_ad(0); 492 } 493 494 int ft_init()495 ft_init() 496 { 497 ut_ad(0); 498 return(HA_ERR_WRONG_COMMAND); 499 } 500 501 FT_INFO* ft_init_ext(uint flags,uint inx,String * key)502 ft_init_ext( 503 uint flags, 504 uint inx, 505 String* key) 506 { 507 ut_ad(0); 508 return(NULL); 509 } 510 511 FT_INFO* ft_init_ext_with_hints(uint inx,String * key,Ft_hints * hints)512 ft_init_ext_with_hints( 513 uint inx, 514 String* key, 515 Ft_hints* hints) 516 { 517 ut_ad(0); 518 return(NULL); 519 } 520 521 int ft_read(uchar * buf)522 ft_read( 523 uchar* buf) 524 { 525 ut_ad(0); 526 return(HA_ERR_WRONG_COMMAND); 527 } 528 529 bool get_foreign_dup_key(char * child_table_name,uint child_table_name_len,char * child_key_name,uint child_key_name_len)530 get_foreign_dup_key( 531 char* child_table_name, 532 uint child_table_name_len, 533 char* child_key_name, 534 uint child_key_name_len) 535 { 536 ut_ad(0); 537 return(false); 538 } 539 540 // TODO: not yet supporting FK. 541 char* get_foreign_key_create_info()542 get_foreign_key_create_info() 543 { 544 return(NULL); 545 } 546 547 // TODO: not yet supporting FK. 548 int get_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)549 get_foreign_key_list( 550 THD* thd, 551 List<FOREIGN_KEY_INFO>* f_key_list) 552 { 553 return(0); 554 } 555 556 // TODO: not yet supporting FK. 557 int get_parent_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)558 get_parent_foreign_key_list( 559 THD* thd, 560 List<FOREIGN_KEY_INFO>* f_key_list) 561 { 562 return(0); 563 } 564 565 // TODO: not yet supporting FK. 566 int get_cascade_foreign_key_table_list(THD * thd,List<st_handler_tablename> * fk_table_list)567 get_cascade_foreign_key_table_list( 568 THD* thd, 569 List<st_handler_tablename>* fk_table_list) 570 { 571 return(0); 572 } 573 574 int read_range_next()575 read_range_next() 576 { 577 return(Partition_helper::ph_read_range_next()); 578 } 579 580 uint32 calculate_key_hash_value(Field ** field_array)581 calculate_key_hash_value( 582 Field** field_array) 583 { 584 return(Partition_helper::ph_calculate_key_hash_value(field_array)); 585 } 586 587 Table_flags table_flags()588 table_flags() const 589 { 590 return(ha_innobase::table_flags() | HA_CAN_REPAIR); 591 } 592 593 void release_auto_increment()594 release_auto_increment() 595 { 596 Partition_helper::ph_release_auto_increment(); 597 } 598 599 /** Implementing Partition_handler interface @see partition_handler.h 600 @{ */ 601 602 /** See Partition_handler. */ 603 void get_dynamic_partition_info(ha_statistics * stat_info,ha_checksum * check_sum,uint part_id)604 get_dynamic_partition_info( 605 ha_statistics* stat_info, 606 ha_checksum* check_sum, 607 uint part_id) 608 { 609 Partition_helper::get_dynamic_partition_info_low( 610 stat_info, 611 check_sum, 612 part_id); 613 } 614 615 uint alter_flags(uint flags MY_ATTRIBUTE ((unused)))616 alter_flags( 617 uint flags MY_ATTRIBUTE((unused))) const 618 { 619 return(HA_PARTITION_FUNCTION_SUPPORTED 620 | HA_FAST_CHANGE_PARTITION); 621 } 622 623 Partition_handler* get_partition_handler()624 get_partition_handler() 625 { 626 return(static_cast<Partition_handler*>(this)); 627 } 628 629 void set_part_info(partition_info * part_info,bool early)630 set_part_info( 631 partition_info* part_info, 632 bool early) 633 { 634 Partition_helper::set_part_info_low(part_info, early); 635 } 636 637 void initialize_partitioning(partition_info * part_info,bool early)638 initialize_partitioning( 639 partition_info* part_info, 640 bool early) 641 { 642 Partition_helper::set_part_info_low(part_info, early); 643 } 644 645 handler* get_handler()646 get_handler() 647 { 648 return(static_cast<handler*>(this)); 649 } 650 /** @} */ 651 652 private: 653 /** Pointer to Ha_innopart_share on the TABLE_SHARE. */ 654 Ha_innopart_share* m_part_share; 655 656 /** ins_node per partition. Synchronized with prebuilt->ins_node 657 when changing partitions. */ 658 ins_node_t** m_ins_node_parts; 659 660 /** upd_node per partition. Synchronized with prebuilt->upd_node 661 when changing partitions. */ 662 upd_node_t** m_upd_node_parts; 663 664 /** blob_heap per partition. Synchronized with prebuilt->blob_heap 665 when changing partitions. */ 666 mem_heap_t** m_blob_heap_parts; 667 668 /** trx_id from the partitions table->def_trx_id. Keep in sync 669 with prebuilt->trx_id when changing partitions. 670 prebuilt only reflects the current partition! */ 671 trx_id_t* m_trx_id_parts; 672 673 /** row_read_type per partition. */ 674 ulint* m_row_read_type_parts; 675 676 /** sql_stat_start per partition. */ 677 uchar* m_sql_stat_start_parts; 678 679 /** persistent cursors per partition. */ 680 btr_pcur_t* m_pcur_parts; 681 682 /** persistent cluster cursors per partition. */ 683 btr_pcur_t* m_clust_pcur_parts; 684 685 /** map from part_id to offset in above two arrays. */ 686 uint16_t* m_pcur_map; 687 688 /** Original m_prebuilt->pcur. */ 689 btr_pcur_t* m_pcur; 690 691 /** Original m_prebuilt->clust_pcur. */ 692 btr_pcur_t* m_clust_pcur; 693 694 /** New partitions during ADD/REORG/... PARTITION. */ 695 Altered_partitions* m_new_partitions; 696 697 /** Clear used ins_nodes and upd_nodes. */ 698 void 699 clear_ins_upd_nodes(); 700 701 /** Clear the blob heaps for all partitions */ 702 void 703 clear_blob_heaps(); 704 705 /** Reset state of file to after 'open'. This function is called 706 after every statement for all tables used by that statement. */ 707 int 708 reset(); 709 710 /** Allocate the array to hold blob heaps for all partitions */ 711 mem_heap_t** 712 alloc_blob_heap_array(); 713 714 /** Free the array that holds blob heaps for all partitions */ 715 void 716 free_blob_heap_array(); 717 718 /** Changes the active index of a handle. 719 @param[in] part_id Use this partition. 720 @param[in] keynr Use this index; MAX_KEY means always 721 clustered index, even if it was internally generated by InnoDB. 722 @return 0 or error code. */ 723 int 724 change_active_index( 725 uint part_id, 726 uint keynr); 727 728 /** Move to next partition and set its index. 729 @return 0 for success else error number. */ 730 int 731 next_partition_index(); 732 733 /** Internally called for initializing auto increment value. 734 Should never be called, but defined to catch such errors. 735 @return 0 on success else error code. */ 736 int 737 innobase_initialize_autoinc(); 738 739 /** Get the index for the current partition 740 @param[in] keynr MySQL index number. 741 @return InnoDB index or NULL. */ 742 dict_index_t* 743 innobase_get_index( 744 uint keynr); 745 746 /** Get the index for a handle. 747 Does not change active index. 748 @param[in] keynr use this index; MAX_KEY means always clustered 749 index, even if it was internally generated by InnoDB. 750 @param[in] part_id From this partition. 751 @return NULL or index instance. */ 752 dict_index_t* 753 innopart_get_index( 754 uint part_id, 755 uint keynr); 756 757 /** Change active partition. 758 Copies needed info into m_prebuilt from the partition specific memory. 759 @param[in] part_id Partition to set as active. */ 760 void 761 set_partition( 762 uint part_id); 763 764 /** Update active partition. 765 Copies needed info from m_prebuilt into the partition specific memory. 766 @param[in] part_id Partition to set as active. */ 767 void 768 update_partition( 769 uint part_id); 770 771 /** Helpers needed by Partition_helper, @see partition_handler.h @{ */ 772 773 /** Set the autoinc column max value. 774 This should only be called once from ha_innobase::open(). 775 Therefore there's no need for a covering lock. 776 @param[in] no_lock If locking should be skipped. Not used! 777 @return 0 on success else error code. */ 778 int 779 initialize_auto_increment( 780 bool /* no_lock */); 781 782 /** Save currently highest auto increment value. 783 @param[in] nr Auto increment value to save. */ 784 void 785 save_auto_increment( 786 ulonglong nr); 787 788 /** Setup the ordered record buffer and the priority queue. 789 @param[in] used_parts Number of used partitions in query. 790 @return false for success, else true. */ 791 int 792 init_record_priority_queue_for_parts( 793 uint used_parts); 794 795 /** Destroy the ordered record buffer and the priority queue. */ 796 void 797 destroy_record_priority_queue_for_parts(); 798 799 /** Prepare for creating new partitions during ALTER TABLE ... 800 PARTITION. 801 @param[in] num_partitions Number of new partitions to be created. 802 @param[in] only_create True if only creating the partition 803 (no open/lock is needed). 804 @return 0 for success else error code. */ 805 int 806 prepare_for_new_partitions( 807 uint num_partitions, 808 bool only_create); 809 810 /** Create a new partition to be filled during ALTER TABLE ... 811 PARTITION. 812 @param[in] table Table to create the partition in. 813 @param[in] create_info Table/partition specific create info. 814 @param[in] part_name Partition name. 815 @param[in] new_part_id Partition id in new table. 816 @param[in] part_elem Partition element. 817 @return 0 for success else error code. */ 818 int 819 create_new_partition( 820 TABLE* table, 821 HA_CREATE_INFO* create_info, 822 const char* part_name, 823 uint new_part_id, 824 partition_element* part_elem); 825 826 /** Close and finalize new partitions. */ 827 void 828 close_new_partitions(); 829 830 /** write row to new partition. 831 @param[in] new_part New partition to write to. 832 @return 0 for success else error code. */ 833 int 834 write_row_in_new_part( 835 uint new_part); 836 837 /** Write a row in specific partition. 838 Stores a row in an InnoDB database, to the table specified in this 839 handle. 840 @param[in] part_id Partition to write to. 841 @param[in] row A row in MySQL format. 842 @return error code. */ 843 int 844 write_row_in_part( 845 uint part_id, 846 uchar* row); 847 848 /** Update a row in partition. 849 Updates a row given as a parameter to a new value. 850 @param[in] part_id Partition to update row in. 851 @param[in] old_row Old row in MySQL format. 852 @param[in] new_row New row in MySQL format. 853 @return error number or 0. */ 854 int 855 update_row_in_part( 856 uint part_id, 857 const uchar* old_row, 858 uchar* new_row); 859 860 /** Deletes a row in partition. 861 @param[in] part_id Partition to delete from. 862 @param[in] row Row to delete in MySQL format. 863 @return error number or 0. */ 864 int 865 delete_row_in_part( 866 uint part_id, 867 const uchar* row); 868 869 /** Return first record in index from a partition. 870 @param[in] part Partition to read from. 871 @param[out] record First record in index in the partition. 872 @return error number or 0. */ 873 int 874 index_first_in_part( 875 uint part, 876 uchar* record); 877 878 /** Return last record in index from a partition. 879 @param[in] part Partition to read from. 880 @param[out] record Last record in index in the partition. 881 @return error number or 0. */ 882 int 883 index_last_in_part( 884 uint part, 885 uchar* record); 886 887 /** Return previous record in index from a partition. 888 @param[in] part Partition to read from. 889 @param[out] record Last record in index in the partition. 890 @return error number or 0. */ 891 int 892 index_prev_in_part( 893 uint part, 894 uchar* record); 895 896 /** Return next record in index from a partition. 897 @param[in] part Partition to read from. 898 @param[out] record Last record in index in the partition. 899 @return error number or 0. */ 900 int 901 index_next_in_part( 902 uint part, 903 uchar* record); 904 905 /** Return next same record in index from a partition. 906 This routine is used to read the next record, but only if the key is 907 the same as supplied in the call. 908 @param[in] part Partition to read from. 909 @param[out] record Last record in index in the partition. 910 @param[in] key Key to match. 911 @param[in] length Length of key. 912 @return error number or 0. */ 913 int 914 index_next_same_in_part( 915 uint part, 916 uchar* record, 917 const uchar* key, 918 uint length); 919 920 /** Start index scan and return first record from a partition. 921 This routine starts an index scan using a start key. The calling 922 function will check the end key on its own. 923 @param[in] part Partition to read from. 924 @param[out] record First matching record in index in the partition. 925 @param[in] key Key to match. 926 @param[in] keypart_map Which part of the key to use. 927 @param[in] find_flag Key condition/direction to use. 928 @return error number or 0. */ 929 int 930 index_read_map_in_part( 931 uint part, 932 uchar* record, 933 const uchar* key, 934 key_part_map keypart_map, 935 enum ha_rkey_function find_flag); 936 937 /** Return last matching record in index from a partition. 938 @param[in] part Partition to read from. 939 @param[out] record Last matching record in index in the partition. 940 @param[in] key Key to match. 941 @param[in] keypart_map Which part of the key to use. 942 @return error number or 0. */ 943 int 944 index_read_last_map_in_part( 945 uint part, 946 uchar* record, 947 const uchar* key, 948 key_part_map keypart_map); 949 950 /** Start index scan and return first record from a partition. 951 This routine starts an index scan using a start and end key. 952 @param[in] part Partition to read from. 953 @param[out] record First matching record in index in the partition. 954 if NULL use table->record[0] as return buffer. 955 @param[in] start_key Start key to match. 956 @param[in] end_key End key to match. 957 @param[in] eq_range Is equal range, start_key == end_key. 958 @param[in] sorted Return rows in sorted order. 959 @return error number or 0. */ 960 int 961 read_range_first_in_part( 962 uint part, 963 uchar* record, 964 const key_range* start_key, 965 const key_range* end_key, 966 bool eq_range, 967 bool sorted); 968 969 /** Return next record in index range scan from a partition. 970 @param[in] part Partition to read from. 971 @param[out] record First matching record in index in the partition. 972 if NULL use table->record[0] as return buffer. 973 @return error number or 0. */ 974 int 975 read_range_next_in_part( 976 uint part, 977 uchar* record); 978 979 /** Start index scan and return first record from a partition. 980 This routine starts an index scan using a start key. The calling 981 function will check the end key on its own. 982 @param[in] part Partition to read from. 983 @param[out] record First matching record in index in the partition. 984 @param[in] index Index to read from. 985 @param[in] key Key to match. 986 @param[in] keypart_map Which part of the key to use. 987 @param[in] find_flag Key condition/direction to use. 988 @return error number or 0. */ 989 int 990 index_read_idx_map_in_part( 991 uint part, 992 uchar* record, 993 uint index, 994 const uchar* key, 995 key_part_map keypart_map, 996 enum ha_rkey_function find_flag); 997 998 /** Initialize random read/scan of a specific partition. 999 @param[in] part_id Partition to initialize. 1000 @param[in] table_scan True for scan else random access. 1001 @return error number or 0. */ 1002 int 1003 rnd_init_in_part( 1004 uint part_id, 1005 bool table_scan); 1006 1007 /** Get next row during scan of a specific partition. 1008 @param[in] part_id Partition to read from. 1009 @param[out] record Next row. 1010 @return error number or 0. */ 1011 int 1012 rnd_next_in_part( 1013 uint part_id, 1014 uchar* record); 1015 1016 /** End random read/scan of a specific partition. 1017 @param[in] part_id Partition to end random read/scan. 1018 @param[in] table_scan True for scan else random access. 1019 @return error number or 0. */ 1020 int 1021 rnd_end_in_part( 1022 uint part_id, 1023 bool table_scan); 1024 1025 /** Get a reference to the current cursor position in the last used 1026 partition. 1027 @param[out] ref Reference (PK if exists else row_id). 1028 @param[in] record Record to position. */ 1029 void 1030 position_in_last_part( 1031 uchar* ref, 1032 const uchar* record); 1033 1034 /** Read row using position using given record to find. 1035 Only useful when position is based on primary key 1036 @param[in] record Current record in MySQL Row Format. 1037 @return error number or 0. */ 1038 int 1039 rnd_pos_by_record( 1040 uchar* record); 1041 1042 /** Copy a cached MySQL record. 1043 @param[out] to_record Where to copy the MySQL record. 1044 @param[in] from_record Which record to copy. */ 1045 void 1046 copy_cached_row( 1047 uchar* to_record, 1048 const uchar* from_record); 1049 /** @} */ 1050 1051 /* Private handler:: functions specific for native InnoDB partitioning. 1052 @see handler.h @{ */ 1053 1054 int 1055 open( 1056 const char* name, 1057 int mode, 1058 uint test_if_locked); 1059 1060 int 1061 close(); 1062 1063 double 1064 scan_time(); 1065 1066 /** Was the last returned row semi consistent read. 1067 In an UPDATE or DELETE, if the row under the cursor was locked by 1068 another transaction, and the engine used an optimistic read of the last 1069 committed row value under the cursor, then the engine returns 1 from 1070 this function. MySQL must NOT try to update this optimistic value. If 1071 the optimistic value does not match the WHERE condition, MySQL can 1072 decide to skip over this row. This can be used to avoid unnecessary 1073 lock waits. 1074 1075 If this method returns true, it will also signal the storage 1076 engine that the next read will be a locking re-read of the row. 1077 @see handler.h and row0mysql.h 1078 @return true if last read was semi consistent else false. */ 1079 bool was_semi_consistent_read(); 1080 1081 /** Try semi consistent read. 1082 Tell the engine whether it should avoid unnecessary lock waits. 1083 If yes, in an UPDATE or DELETE, if the row under the cursor was locked 1084 by another transaction, the engine may try an optimistic read of 1085 the last committed row value under the cursor. 1086 @see handler.h and row0mysql.h 1087 @param[in] yes Should semi-consistent read be used. */ 1088 void try_semi_consistent_read( 1089 bool yes); 1090 1091 /** Removes a lock on a row. 1092 Removes a new lock set on a row, if it was not read optimistically. 1093 This can be called after a row has been read in the processing of 1094 an UPDATE or a DELETE query. @see ha_innobase::unlock_row(). */ 1095 void unlock_row(); 1096 1097 int 1098 index_init( 1099 uint index, 1100 bool sorted); 1101 1102 int 1103 index_end(); 1104 1105 int rnd_init(bool scan)1106 rnd_init( 1107 bool scan) 1108 { 1109 return(Partition_helper::ph_rnd_init(scan)); 1110 } 1111 1112 int rnd_end()1113 rnd_end() 1114 { 1115 return(Partition_helper::ph_rnd_end()); 1116 } 1117 1118 int 1119 external_lock( 1120 THD* thd, 1121 int lock_type); 1122 1123 THR_LOCK_DATA** 1124 store_lock( 1125 THD* thd, 1126 THR_LOCK_DATA** to, 1127 thr_lock_type lock_type); 1128 1129 int write_row(uchar * record)1130 write_row( 1131 uchar* record) 1132 { 1133 return(Partition_helper::ph_write_row(record)); 1134 } 1135 1136 int update_row(const uchar * old_record,uchar * new_record)1137 update_row( 1138 const uchar* old_record, 1139 uchar* new_record) 1140 { 1141 return(Partition_helper::ph_update_row(old_record, new_record)); 1142 } 1143 1144 int delete_row(const uchar * record)1145 delete_row( 1146 const uchar* record) 1147 { 1148 return(Partition_helper::ph_delete_row(record)); 1149 } 1150 /** @} */ 1151 1152 /** Truncate partition. 1153 Called from Partition_handler::trunctate_partition(). */ 1154 int 1155 truncate_partition_low(); 1156 1157 /** Change partitions according to ALTER TABLE ... PARTITION ... 1158 Called from Partition_handler::change_partitions(). 1159 @param[in] create_info Table create info. 1160 @param[in] path Path including db/table_name. 1161 @param[out] copied Number of copied rows. 1162 @param[out] deleted Number of deleted rows. 1163 @return 0 for success or error code. */ 1164 int change_partitions_low(HA_CREATE_INFO * create_info,const char * path,ulonglong * const copied,ulonglong * const deleted)1165 change_partitions_low( 1166 HA_CREATE_INFO* create_info, 1167 const char* path, 1168 ulonglong* const copied, 1169 ulonglong* const deleted) 1170 { 1171 return(Partition_helper::change_partitions( 1172 create_info, 1173 path, 1174 copied, 1175 deleted)); 1176 } 1177 1178 /** Access methods to protected areas in handler to avoid adding 1179 friend class Partition_helper in class handler. 1180 @see partition_handler.h @{ */ 1181 1182 THD* get_thd()1183 get_thd() const 1184 { 1185 return ha_thd(); 1186 } 1187 1188 TABLE* get_table()1189 get_table() const 1190 { 1191 return table; 1192 } 1193 1194 bool get_eq_range()1195 get_eq_range() const 1196 { 1197 return eq_range; 1198 } 1199 1200 void set_eq_range(bool eq_range_arg)1201 set_eq_range(bool eq_range_arg) 1202 { 1203 eq_range= eq_range_arg; 1204 } 1205 1206 void set_range_key_part(KEY_PART_INFO * key_part)1207 set_range_key_part(KEY_PART_INFO *key_part) 1208 { 1209 range_key_part= key_part; 1210 } 1211 /** @} */ 1212 1213 /** Fill in data_dir_path and tablespace name from internal data 1214 dictionary. 1215 @param part_elem Partition element to fill. 1216 @param ib_table InnoDB table to copy from. */ 1217 void 1218 update_part_elem( 1219 partition_element* part_elem, 1220 dict_table_t* ib_table); 1221 protected: 1222 /* Protected handler:: functions specific for native InnoDB partitioning. 1223 @see handler.h @{ */ 1224 1225 int rnd_next(uchar * record)1226 rnd_next( 1227 uchar* record) 1228 { 1229 return(Partition_helper::ph_rnd_next(record)); 1230 } 1231 1232 int 1233 rnd_pos( 1234 uchar* record, 1235 uchar* pos); 1236 1237 #ifdef WL6742 1238 /* Removing WL6742 as part of Bug 23046302 */ 1239 int 1240 records( 1241 ha_rows* num_rows); 1242 #endif 1243 1244 int index_next(uchar * record)1245 index_next( 1246 uchar* record) 1247 { 1248 return(Partition_helper::ph_index_next(record)); 1249 } 1250 1251 int index_next_same(uchar * record,const uchar * key,uint keylen)1252 index_next_same( 1253 uchar* record, 1254 const uchar* key, 1255 uint keylen) 1256 { 1257 return(Partition_helper::ph_index_next_same(record, key, keylen)); 1258 } 1259 1260 int index_prev(uchar * record)1261 index_prev( 1262 uchar* record) 1263 { 1264 return(Partition_helper::ph_index_prev(record)); 1265 } 1266 1267 int index_first(uchar * record)1268 index_first( 1269 uchar* record) 1270 { 1271 return(Partition_helper::ph_index_first(record)); 1272 } 1273 1274 int index_last(uchar * record)1275 index_last( 1276 uchar* record) 1277 { 1278 return(Partition_helper::ph_index_last(record)); 1279 } 1280 1281 int index_read_last_map(uchar * record,const uchar * key,key_part_map keypart_map)1282 index_read_last_map( 1283 uchar* record, 1284 const uchar* key, 1285 key_part_map keypart_map) 1286 { 1287 return(Partition_helper::ph_index_read_last_map( 1288 record, 1289 key, 1290 keypart_map)); 1291 } 1292 1293 int index_read_map(uchar * buf,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)1294 index_read_map( 1295 uchar* buf, 1296 const uchar* key, 1297 key_part_map keypart_map, 1298 enum ha_rkey_function find_flag) 1299 { 1300 return(Partition_helper::ph_index_read_map( 1301 buf, 1302 key, 1303 keypart_map, 1304 find_flag)); 1305 } 1306 1307 int index_read_idx_map(uchar * buf,uint index,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)1308 index_read_idx_map( 1309 uchar* buf, 1310 uint index, 1311 const uchar* key, 1312 key_part_map keypart_map, 1313 enum ha_rkey_function find_flag) 1314 { 1315 return(Partition_helper::ph_index_read_idx_map( 1316 buf, 1317 index, 1318 key, 1319 keypart_map, 1320 find_flag)); 1321 } 1322 /** @} */ 1323 1324 /** Updates and return statistics. 1325 Returns statistics information of the table to the MySQL interpreter, 1326 in various fields of the handle object. 1327 @param[in] flag Flags for what to update and return. 1328 @param[in] is_analyze True if called from ::analyze(). 1329 @return HA_ERR_* error code or 0. */ 1330 int 1331 info_low( 1332 uint flag, 1333 bool is_analyze); 1334 }; 1335 #endif /* ha_innopart_h */ 1336