| 1 | #ifndef PARTITION_INFO_INCLUDED |
| 2 | #define PARTITION_INFO_INCLUDED |
| 3 | |
| 4 | /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; version 2 of the License. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | GNU General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU General Public License |
| 16 | along with this program; if not, write to the Free Software |
| 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
| 18 | |
| 19 | #ifdef USE_PRAGMA_INTERFACE |
| 20 | #pragma interface /* gcc class implementation */ |
| 21 | #endif |
| 22 | |
| 23 | #include "sql_class.h" |
| 24 | #include "partition_element.h" |
| 25 | #include "sql_partition.h" |
| 26 | |
| 27 | class partition_info; |
| 28 | struct TABLE_LIST; |
| 29 | /* Some function typedefs */ |
| 30 | typedef int (*get_part_id_func)(partition_info *part_info, uint32 *part_id, |
| 31 | longlong *func_value); |
| 32 | typedef int (*get_subpart_id_func)(partition_info *part_info, uint32 *part_id); |
| 33 | typedef bool (*check_constants_func)(THD *thd, partition_info *part_info); |
| 34 | |
| 35 | struct st_ddl_log_memory_entry; |
| 36 | |
| 37 | struct Vers_part_info : public Sql_alloc |
| 38 | { |
| 39 | Vers_part_info() : |
| 40 | limit(0), |
| 41 | now_part(NULL), |
| 42 | hist_part(NULL) |
| 43 | { |
| 44 | interval.type= INTERVAL_LAST; |
| 45 | } |
| 46 | Vers_part_info(Vers_part_info &src) : |
| 47 | interval(src.interval), |
| 48 | limit(src.limit), |
| 49 | now_part(NULL), |
| 50 | hist_part(NULL) |
| 51 | { |
| 52 | } |
| 53 | bool initialized() |
| 54 | { |
| 55 | if (now_part) |
| 56 | { |
| 57 | DBUG_ASSERT(now_part->id != UINT_MAX32); |
| 58 | DBUG_ASSERT(now_part->type() == partition_element::CURRENT); |
| 59 | if (hist_part) |
| 60 | { |
| 61 | DBUG_ASSERT(hist_part->id != UINT_MAX32); |
| 62 | DBUG_ASSERT(hist_part->type() == partition_element::HISTORY); |
| 63 | } |
| 64 | return true; |
| 65 | } |
| 66 | return false; |
| 67 | } |
| 68 | struct { |
| 69 | my_time_t start; |
| 70 | INTERVAL step; |
| 71 | enum interval_type type; |
| 72 | bool is_set() { return type < INTERVAL_LAST; } |
| 73 | } interval; |
| 74 | ulonglong limit; |
| 75 | partition_element *now_part; |
| 76 | partition_element *hist_part; |
| 77 | }; |
| 78 | |
| 79 | class partition_info : public Sql_alloc |
| 80 | { |
| 81 | public: |
| 82 | /* |
| 83 | * Here comes a set of definitions needed for partitioned table handlers. |
| 84 | */ |
| 85 | List<partition_element> partitions; |
| 86 | List<partition_element> temp_partitions; |
| 87 | |
| 88 | List<const char> part_field_list; |
| 89 | List<const char> subpart_field_list; |
| 90 | |
| 91 | /* |
| 92 | If there is no subpartitioning, use only this func to get partition ids. |
| 93 | If there is subpartitioning, use the this func to get partition id when |
| 94 | you have both partition and subpartition fields. |
| 95 | */ |
| 96 | get_part_id_func get_partition_id; |
| 97 | |
| 98 | /* Get partition id when we don't have subpartition fields */ |
| 99 | get_part_id_func get_part_partition_id; |
| 100 | |
| 101 | /* |
| 102 | Get subpartition id when we have don't have partition fields by we do |
| 103 | have subpartition ids. |
| 104 | Mikael said that for given constant tuple |
| 105 | {subpart_field1, ..., subpart_fieldN} the subpartition id will be the |
| 106 | same in all subpartitions |
| 107 | */ |
| 108 | get_subpart_id_func get_subpartition_id; |
| 109 | |
| 110 | /* |
| 111 | When we have various string fields we might need some preparation |
| 112 | before and clean-up after calling the get_part_id_func's. We need |
| 113 | one such method for get_part_partition_id and one for |
| 114 | get_subpartition_id. |
| 115 | */ |
| 116 | get_part_id_func get_part_partition_id_charset; |
| 117 | get_subpart_id_func get_subpartition_id_charset; |
| 118 | |
| 119 | check_constants_func check_constants; |
| 120 | |
| 121 | /* NULL-terminated array of fields used in partitioned expression */ |
| 122 | Field **part_field_array; |
| 123 | Field **subpart_field_array; |
| 124 | Field **part_charset_field_array; |
| 125 | Field **subpart_charset_field_array; |
| 126 | /* |
| 127 | Array of all fields used in partition and subpartition expression, |
| 128 | without duplicates, NULL-terminated. |
| 129 | */ |
| 130 | Field **full_part_field_array; |
| 131 | /* |
| 132 | Set of all fields used in partition and subpartition expression. |
| 133 | Required for testing of partition fields in write_set when |
| 134 | updating. We need to set all bits in read_set because the row may |
| 135 | need to be inserted in a different [sub]partition. |
| 136 | */ |
| 137 | MY_BITMAP full_part_field_set; |
| 138 | |
| 139 | /* |
| 140 | When we have a field that requires transformation before calling the |
| 141 | partition functions we must allocate field buffers for the field of |
| 142 | the fields in the partition function. |
| 143 | */ |
| 144 | uchar **part_field_buffers; |
| 145 | uchar **subpart_field_buffers; |
| 146 | uchar **restore_part_field_ptrs; |
| 147 | uchar **restore_subpart_field_ptrs; |
| 148 | |
| 149 | Item *part_expr; |
| 150 | Item *subpart_expr; |
| 151 | |
| 152 | Item *item_free_list; |
| 153 | |
| 154 | struct st_ddl_log_memory_entry *first_log_entry; |
| 155 | struct st_ddl_log_memory_entry *exec_log_entry; |
| 156 | struct st_ddl_log_memory_entry *frm_log_entry; |
| 157 | |
| 158 | /* |
| 159 | Bitmaps of partitions used by the current query. |
| 160 | * read_partitions - partitions to be used for reading. |
| 161 | * lock_partitions - partitions that must be locked (read or write). |
| 162 | Usually read_partitions is the same set as lock_partitions, but |
| 163 | in case of UPDATE the WHERE clause can limit the read_partitions set, |
| 164 | but not neccesarily the lock_partitions set. |
| 165 | Usage pattern: |
| 166 | * Initialized in ha_partition::open(). |
| 167 | * read+lock_partitions is set according to explicit PARTITION, |
| 168 | WL#5217, in open_and_lock_tables(). |
| 169 | * Bits in read_partitions can be cleared in prune_partitions() |
| 170 | in the optimizing step. |
| 171 | (WL#4443 is about allowing prune_partitions() to affect lock_partitions |
| 172 | and be done before locking too). |
| 173 | * When the partition enabled handler get an external_lock call it locks |
| 174 | all partitions in lock_partitions (and remembers which partitions it |
| 175 | locked, so that it can unlock them later). In case of LOCK TABLES it will |
| 176 | lock all partitions, and keep them locked while lock_partitions can |
| 177 | change for each statement under LOCK TABLES. |
| 178 | * Freed at the same time item_free_list is freed. |
| 179 | */ |
| 180 | MY_BITMAP read_partitions; |
| 181 | MY_BITMAP lock_partitions; |
| 182 | bool bitmaps_are_initialized; |
| 183 | |
| 184 | union { |
| 185 | longlong *range_int_array; |
| 186 | LIST_PART_ENTRY *list_array; |
| 187 | part_column_list_val *range_col_array; |
| 188 | part_column_list_val *list_col_array; |
| 189 | }; |
| 190 | |
| 191 | Vers_part_info *vers_info; |
| 192 | |
| 193 | /******************************************** |
| 194 | * INTERVAL ANALYSIS |
| 195 | ********************************************/ |
| 196 | /* |
| 197 | Partitioning interval analysis function for partitioning, or NULL if |
| 198 | interval analysis is not supported for this kind of partitioning. |
| 199 | */ |
| 200 | get_partitions_in_range_iter get_part_iter_for_interval; |
| 201 | /* |
| 202 | Partitioning interval analysis function for subpartitioning, or NULL if |
| 203 | interval analysis is not supported for this kind of partitioning. |
| 204 | */ |
| 205 | get_partitions_in_range_iter get_subpart_iter_for_interval; |
| 206 | |
| 207 | /******************************************** |
| 208 | * INTERVAL ANALYSIS ENDS |
| 209 | ********************************************/ |
| 210 | |
| 211 | longlong err_value; |
| 212 | char* part_info_string; |
| 213 | |
| 214 | partition_element *curr_part_elem; // part or sub part |
| 215 | partition_element *current_partition; // partition |
| 216 | part_elem_value *curr_list_val; |
| 217 | uint curr_list_object; |
| 218 | uint num_columns; |
| 219 | |
| 220 | TABLE *table; |
| 221 | /* |
| 222 | These key_map's are used for Partitioning to enable quick decisions |
| 223 | on whether we can derive more information about which partition to |
| 224 | scan just by looking at what index is used. |
| 225 | */ |
| 226 | key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF; |
| 227 | key_map some_fields_in_PF; |
| 228 | |
| 229 | handlerton *default_engine_type; |
| 230 | partition_type part_type; |
| 231 | partition_type subpart_type; |
| 232 | |
| 233 | uint part_info_len; |
| 234 | |
| 235 | uint num_parts; |
| 236 | uint num_subparts; |
| 237 | uint count_curr_subparts; // used during parsing |
| 238 | |
| 239 | uint num_list_values; |
| 240 | |
| 241 | uint num_part_fields; |
| 242 | uint num_subpart_fields; |
| 243 | uint num_full_part_fields; |
| 244 | |
| 245 | uint has_null_part_id; |
| 246 | uint32 default_partition_id; |
| 247 | /* |
| 248 | This variable is used to calculate the partition id when using |
| 249 | LINEAR KEY/HASH. This functionality is kept in the MySQL Server |
| 250 | but mainly of use to handlers supporting partitioning. |
| 251 | */ |
| 252 | uint16 linear_hash_mask; |
| 253 | /* |
| 254 | PARTITION BY KEY ALGORITHM=N |
| 255 | Which algorithm to use for hashing the fields. |
| 256 | N = 1 - Use 5.1 hashing (numeric fields are hashed as binary) |
| 257 | N = 2 - Use 5.5 hashing (numeric fields are hashed like latin1 bytes) |
| 258 | */ |
| 259 | enum enum_key_algorithm |
| 260 | { |
| 261 | KEY_ALGORITHM_NONE= 0, |
| 262 | KEY_ALGORITHM_51= 1, |
| 263 | KEY_ALGORITHM_55= 2 |
| 264 | }; |
| 265 | enum_key_algorithm key_algorithm; |
| 266 | |
| 267 | /* Only the number of partitions defined (uses default names and options). */ |
| 268 | bool use_default_partitions; |
| 269 | bool use_default_num_partitions; |
| 270 | /* Only the number of subpartitions defined (uses default names etc.). */ |
| 271 | bool use_default_subpartitions; |
| 272 | bool use_default_num_subpartitions; |
| 273 | bool default_partitions_setup; |
| 274 | bool defined_max_value; |
| 275 | inline bool has_default_partititon() |
| 276 | { |
| 277 | return (part_type == LIST_PARTITION && defined_max_value); |
| 278 | } |
| 279 | bool list_of_part_fields; // KEY or COLUMNS PARTITIONING |
| 280 | bool list_of_subpart_fields; // KEY SUBPARTITIONING |
| 281 | bool linear_hash_ind; // LINEAR HASH/KEY |
| 282 | bool fixed; |
| 283 | bool is_auto_partitioned; |
| 284 | bool has_null_value; |
| 285 | bool column_list; // COLUMNS PARTITIONING, 5.5+ |
| 286 | |
| 287 | partition_info() |
| 288 | : get_partition_id(NULL), get_part_partition_id(NULL), |
| 289 | get_subpartition_id(NULL), |
| 290 | part_field_array(NULL), subpart_field_array(NULL), |
| 291 | part_charset_field_array(NULL), |
| 292 | subpart_charset_field_array(NULL), |
| 293 | full_part_field_array(NULL), |
| 294 | part_field_buffers(NULL), subpart_field_buffers(NULL), |
| 295 | restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL), |
| 296 | part_expr(NULL), subpart_expr(NULL), item_free_list(NULL), |
| 297 | first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL), |
| 298 | bitmaps_are_initialized(FALSE), |
| 299 | list_array(NULL), vers_info(NULL), err_value(0), |
| 300 | part_info_string(NULL), |
| 301 | curr_part_elem(NULL), current_partition(NULL), |
| 302 | curr_list_object(0), num_columns(0), table(NULL), |
| 303 | default_engine_type(NULL), |
| 304 | part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION), |
| 305 | part_info_len(0), |
| 306 | num_parts(0), num_subparts(0), |
| 307 | count_curr_subparts(0), |
| 308 | num_list_values(0), num_part_fields(0), num_subpart_fields(0), |
| 309 | num_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0), |
| 310 | key_algorithm(KEY_ALGORITHM_NONE), |
| 311 | use_default_partitions(TRUE), use_default_num_partitions(TRUE), |
| 312 | use_default_subpartitions(TRUE), use_default_num_subpartitions(TRUE), |
| 313 | default_partitions_setup(FALSE), defined_max_value(FALSE), |
| 314 | list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), |
| 315 | linear_hash_ind(FALSE), fixed(FALSE), |
| 316 | is_auto_partitioned(FALSE), |
| 317 | has_null_value(FALSE), column_list(FALSE) |
| 318 | { |
| 319 | all_fields_in_PF.clear_all(); |
| 320 | all_fields_in_PPF.clear_all(); |
| 321 | all_fields_in_SPF.clear_all(); |
| 322 | some_fields_in_PF.clear_all(); |
| 323 | partitions.empty(); |
| 324 | temp_partitions.empty(); |
| 325 | part_field_list.empty(); |
| 326 | subpart_field_list.empty(); |
| 327 | } |
| 328 | ~partition_info() {} |
| 329 | |
| 330 | partition_info *get_clone(THD *thd); |
| 331 | bool set_named_partition_bitmap(const char *part_name, size_t length); |
| 332 | bool set_partition_bitmaps(List<String> *partition_names); |
| 333 | bool set_partition_bitmaps_from_table(TABLE_LIST *table_list); |
| 334 | /* Answers the question if subpartitioning is used for a certain table */ |
| 335 | bool is_sub_partitioned() |
| 336 | { |
| 337 | return (subpart_type == NOT_A_PARTITION ? FALSE : TRUE); |
| 338 | } |
| 339 | |
| 340 | /* Returns the total number of partitions on the leaf level */ |
| 341 | uint get_tot_partitions() |
| 342 | { |
| 343 | return num_parts * (is_sub_partitioned() ? num_subparts : 1); |
| 344 | } |
| 345 | |
| 346 | bool set_up_defaults_for_partitioning(THD *thd, handler *file, |
| 347 | HA_CREATE_INFO *info, |
| 348 | uint start_no); |
| 349 | const char *find_duplicate_field(); |
| 350 | char *find_duplicate_name(); |
| 351 | bool check_engine_mix(handlerton *engine_type, bool default_engine); |
| 352 | bool check_partition_info(THD *thd, handlerton **eng_type, |
| 353 | handler *file, HA_CREATE_INFO *info, |
| 354 | partition_info *add_or_reorg_part= NULL); |
| 355 | void print_no_partition_found(TABLE *table, myf errflag); |
| 356 | void print_debug(const char *str, uint*); |
| 357 | Item* get_column_item(Item *item, Field *field); |
| 358 | int fix_partition_values(THD *thd, |
| 359 | part_elem_value *val, |
| 360 | partition_element *part_elem); |
| 361 | bool fix_column_value_functions(THD *thd, |
| 362 | part_elem_value *val, |
| 363 | uint part_id); |
| 364 | bool fix_parser_data(THD *thd); |
| 365 | int add_max_value(THD *thd); |
| 366 | void init_col_val(part_column_list_val *col_val, Item *item); |
| 367 | int reorganize_into_single_field_col_val(THD *thd); |
| 368 | part_column_list_val *add_column_value(THD *thd); |
| 369 | bool set_part_expr(THD *thd, char *start_token, Item *item_ptr, |
| 370 | char *end_token, bool is_subpart); |
| 371 | bool set_up_charset_field_preps(THD *thd); |
| 372 | bool check_partition_field_length(); |
| 373 | bool init_column_part(THD *thd); |
| 374 | bool add_column_list_value(THD *thd, Item *item); |
| 375 | partition_element *get_part_elem(const char *partition_name, char *file_name, |
| 376 | size_t file_name_size, uint32 *part_id); |
| 377 | void report_part_expr_error(bool use_subpart_expr); |
| 378 | bool has_same_partitioning(partition_info *new_part_info); |
| 379 | bool error_if_requires_values() const; |
| 380 | private: |
| 381 | bool set_up_default_partitions(THD *thd, handler *file, HA_CREATE_INFO *info, |
| 382 | uint start_no); |
| 383 | bool set_up_default_subpartitions(THD *thd, handler *file, |
| 384 | HA_CREATE_INFO *info); |
| 385 | char *create_default_partition_names(THD *thd, uint part_no, uint num_parts, |
| 386 | uint start_no); |
| 387 | char *create_default_subpartition_name(THD *thd, uint subpart_no, |
| 388 | const char *part_name); |
| 389 | // FIXME: prune_partition_bitmaps() is duplicate of set_read_partitions() |
| 390 | bool prune_partition_bitmaps(List<String> *partition_names); |
| 391 | bool add_named_partition(const char *part_name, size_t length); |
| 392 | public: |
| 393 | bool set_read_partitions(List<char> *partition_names); |
| 394 | bool has_unique_name(partition_element *element); |
| 395 | |
| 396 | bool vers_init_info(THD *thd); |
| 397 | bool vers_set_interval(Item *item, interval_type int_type, my_time_t start) |
| 398 | { |
| 399 | DBUG_ASSERT(part_type == VERSIONING_PARTITION); |
| 400 | vers_info->interval.type= int_type; |
| 401 | vers_info->interval.start= start; |
| 402 | return get_interval_value(item, int_type, &vers_info->interval.step) || |
| 403 | vers_info->interval.step.neg || vers_info->interval.step.second_part || |
| 404 | !(vers_info->interval.step.year || vers_info->interval.step.month || |
| 405 | vers_info->interval.step.day || vers_info->interval.step.hour || |
| 406 | vers_info->interval.step.minute || vers_info->interval.step.second); |
| 407 | } |
| 408 | bool vers_set_limit(ulonglong limit) |
| 409 | { |
| 410 | DBUG_ASSERT(part_type == VERSIONING_PARTITION); |
| 411 | vers_info->limit= limit; |
| 412 | return !limit; |
| 413 | } |
| 414 | void vers_set_hist_part(THD *thd); |
| 415 | bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */ |
| 416 | partition_element *get_partition(uint part_id) |
| 417 | { |
| 418 | List_iterator<partition_element> it(partitions); |
| 419 | partition_element *el; |
| 420 | while ((el= it++)) |
| 421 | { |
| 422 | if (el->id == part_id) |
| 423 | return el; |
| 424 | } |
| 425 | return NULL; |
| 426 | } |
| 427 | }; |
| 428 | |
| 429 | uint32 get_next_partition_id_range(struct st_partition_iter* part_iter); |
| 430 | bool check_partition_dirs(partition_info *part_info); |
| 431 | |
| 432 | /* Initialize the iterator to return a single partition with given part_id */ |
| 433 | |
| 434 | static inline void init_single_partition_iterator(uint32 part_id, |
| 435 | PARTITION_ITERATOR *part_iter) |
| 436 | { |
| 437 | part_iter->part_nums.start= part_iter->part_nums.cur= part_id; |
| 438 | part_iter->part_nums.end= part_id+1; |
| 439 | part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; |
| 440 | part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE; |
| 441 | part_iter->get_next= get_next_partition_id_range; |
| 442 | } |
| 443 | |
| 444 | /* Initialize the iterator to enumerate all partitions */ |
| 445 | static inline |
| 446 | void init_all_partitions_iterator(partition_info *part_info, |
| 447 | PARTITION_ITERATOR *part_iter) |
| 448 | { |
| 449 | part_iter->part_nums.start= part_iter->part_nums.cur= 0; |
| 450 | part_iter->part_nums.end= part_info->num_parts; |
| 451 | part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; |
| 452 | part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE; |
| 453 | part_iter->get_next= get_next_partition_id_range; |
| 454 | } |
| 455 | |
| 456 | #endif /* PARTITION_INFO_INCLUDED */ |
| 457 | |