1 /* Copyright (c) 2006, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /* Some general useful functions */
24
25 // Required to get server definitions for mysql/plugin.h right
26 #include "sql_plugin.h"
27 #include "partition_info.h" // LIST_PART_ENTRY
28 // NOT_A_PARTITION_ID
29 #include "sql_parse.h" // test_if_data_home_dir
30 #include "auth_common.h" // *_ACL
31 #include "table.h" // TABLE_LIST
32 #include "my_bitmap.h" // bitmap*
33 #include "sql_base.h" // fill_record
34 #include "table_trigger_dispatcher.h" // Table_trigger_dispatcher
35 #include "trigger_chain.h" // Trigger_chain
36 #include "partitioning/partition_handler.h" // PART_DEF_NAME, Partition_share
37 #include "sql_tablespace.h" // check_tablespace_name
38
get_clone(bool reset)39 partition_info *partition_info::get_clone(bool reset /* = false */)
40 {
41 DBUG_ENTER("partition_info::get_clone");
42 List_iterator<partition_element> part_it(partitions);
43 partition_element *part;
44 partition_info *clone= new partition_info(*this);
45 if (!clone)
46 {
47 mem_alloc_error(sizeof(partition_info));
48 DBUG_RETURN(NULL);
49 }
50 memset(&(clone->read_partitions), 0, sizeof(clone->read_partitions));
51 memset(&(clone->lock_partitions), 0, sizeof(clone->lock_partitions));
52 clone->bitmaps_are_initialized= FALSE;
53 clone->partitions.empty();
54 clone->temp_partitions.empty();
55
56 while ((part= (part_it++)))
57 {
58 List_iterator<partition_element> subpart_it(part->subpartitions);
59 partition_element *subpart;
60 partition_element *part_clone= new partition_element(*part);
61 if (!part_clone)
62 {
63 mem_alloc_error(sizeof(partition_element));
64 DBUG_RETURN(NULL);
65 }
66
67 /*
68 Mark that RANGE and LIST values needs to be fixed so that we don't
69 use old values. fix_column_value_functions would evaluate the values
70 from Item expression.
71 */
72 if (reset)
73 {
74 clone->defined_max_value = false;
75 List_iterator<part_elem_value> list_it(part_clone->list_val_list);
76 while (part_elem_value *list_value= list_it++)
77 {
78 part_column_list_val *col_val= list_value->col_val_array;
79 for (uint i= 0; i < num_columns; col_val++, i++)
80 {
81 col_val->fixed= 0;
82 }
83 }
84 }
85
86 part_clone->subpartitions.empty();
87 while ((subpart= (subpart_it++)))
88 {
89 partition_element *subpart_clone= new partition_element(*subpart);
90 if (!subpart_clone)
91 {
92 mem_alloc_error(sizeof(partition_element));
93 DBUG_RETURN(NULL);
94 }
95 part_clone->subpartitions.push_back(subpart_clone);
96 }
97 clone->partitions.push_back(part_clone);
98 }
99 DBUG_RETURN(clone);
100 }
101
get_full_clone()102 partition_info *partition_info::get_full_clone()
103 {
104 partition_info *clone;
105 DBUG_ENTER("partition_info::get_full_clone");
106 clone= get_clone();
107 if (!clone)
108 DBUG_RETURN(NULL);
109 memcpy(&clone->read_partitions, &read_partitions, sizeof(read_partitions));
110 memcpy(&clone->lock_partitions, &lock_partitions, sizeof(lock_partitions));
111 clone->bitmaps_are_initialized= bitmaps_are_initialized;
112 DBUG_RETURN(clone);
113 }
114
115 /**
116 Mark named [sub]partition to be used/locked.
117
118 @param part_name Partition name to match.
119 @param length Partition name length.
120
121 @return Success if partition found
122 @retval true Partition found
123 @retval false Partition not found
124 */
125
add_named_partition(const char * part_name,size_t length)126 bool partition_info::add_named_partition(const char *part_name,
127 size_t length)
128 {
129 HASH *part_name_hash;
130 PART_NAME_DEF *part_def;
131 Partition_share *part_share;
132 DBUG_ENTER("partition_info::add_named_partition");
133 assert(table && table->s && table->s->ha_share);
134 part_share= static_cast<Partition_share*>((table->s->ha_share));
135 assert(part_share->partition_name_hash_initialized);
136 part_name_hash= &part_share->partition_name_hash;
137 assert(part_name_hash->records);
138
139 part_def= (PART_NAME_DEF*) my_hash_search(part_name_hash,
140 (const uchar*) part_name,
141 length);
142 if (!part_def)
143 {
144 my_error(ER_UNKNOWN_PARTITION, MYF(0), part_name, table->alias);
145 DBUG_RETURN(true);
146 }
147
148 if (part_def->is_subpart)
149 {
150 bitmap_set_bit(&read_partitions, part_def->part_id);
151 }
152 else
153 {
154 if (is_sub_partitioned())
155 {
156 /* Mark all subpartitions in the partition */
157 uint j, start= part_def->part_id;
158 uint end= start + num_subparts;
159 for (j= start; j < end; j++)
160 bitmap_set_bit(&read_partitions, j);
161 }
162 else
163 bitmap_set_bit(&read_partitions, part_def->part_id);
164 }
165 DBUG_PRINT("info", ("Found partition %u is_subpart %d for name %s",
166 part_def->part_id, part_def->is_subpart,
167 part_name));
168 DBUG_RETURN(false);
169 }
170
171
172 /**
173 Mark named [sub]partition to be used/locked.
174
175 @param part_elem Partition element that matched.
176 */
177
set_named_partition_bitmap(const char * part_name,size_t length)178 bool partition_info::set_named_partition_bitmap(const char *part_name,
179 size_t length)
180 {
181 DBUG_ENTER("partition_info::set_named_partition_bitmap");
182 bitmap_clear_all(&read_partitions);
183 if (add_named_partition(part_name, length))
184 DBUG_RETURN(true);
185 bitmap_copy(&lock_partitions, &read_partitions);
186 DBUG_RETURN(false);
187 }
188
189
190
191 /**
192 Prune away partitions not mentioned in the PARTITION () clause,
193 if used.
194
195 @param table_list Table list pointing to table to prune.
196
197 @return Operation status
198 @retval false Success
199 @retval true Failure
200 */
set_read_partitions(List<String> * partition_names)201 bool partition_info::set_read_partitions(List<String> *partition_names)
202 {
203 DBUG_ENTER("partition_info::set_read_partitions");
204 if (!partition_names || !partition_names->elements)
205 {
206 DBUG_RETURN(true);
207 }
208
209 uint num_names= partition_names->elements;
210 List_iterator<String> partition_names_it(*partition_names);
211 uint i= 0;
212 /*
213 TODO: When adding support for FK in partitioned tables, the referenced
214 table must probably lock all partitions for read, and also write depending
215 of ON DELETE/UPDATE.
216 */
217 bitmap_clear_all(&read_partitions);
218
219 /* No check for duplicate names or overlapping partitions/subpartitions. */
220
221 DBUG_PRINT("info", ("Searching through partition_name_hash"));
222 do
223 {
224 String *part_name_str= partition_names_it++;
225 if (add_named_partition(part_name_str->c_ptr(), part_name_str->length()))
226 DBUG_RETURN(true);
227 } while (++i < num_names);
228 DBUG_RETURN(false);
229 }
230
231
232 /**
233 Set read/lock_partitions bitmap over non pruned partitions
234
235 @param table_list Possible TABLE_LIST which can contain
236 list of partition names to query
237
238 @return Operation status
239 @retval FALSE OK
240 @retval TRUE Failed to allocate memory for bitmap or list of partitions
241 did not match
242
243 @note OK to call multiple times without the need for free_bitmaps.
244 */
245
set_partition_bitmaps(TABLE_LIST * table_list)246 bool partition_info::set_partition_bitmaps(TABLE_LIST *table_list)
247 {
248 DBUG_ENTER("partition_info::set_partition_bitmaps");
249
250 assert(bitmaps_are_initialized);
251 assert(table);
252 is_pruning_completed= false;
253 if (!bitmaps_are_initialized)
254 DBUG_RETURN(TRUE);
255
256 if (table_list &&
257 table_list->partition_names &&
258 table_list->partition_names->elements)
259 {
260 if (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)
261 {
262 /*
263 Don't allow PARTITION () clause on a NDB tables yet.
264 TODO: Add partition name handling to NDB/partition_info.
265 which is currently ha_partition specific.
266 */
267 my_error(ER_PARTITION_CLAUSE_ON_NONPARTITIONED, MYF(0));
268 DBUG_RETURN(true);
269 }
270 if (set_read_partitions(table_list->partition_names))
271 DBUG_RETURN(TRUE);
272 }
273 else
274 {
275 bitmap_set_all(&read_partitions);
276 DBUG_PRINT("info", ("Set all partitions"));
277 }
278 bitmap_copy(&lock_partitions, &read_partitions);
279 assert(bitmap_get_first_set(&lock_partitions) != MY_BIT_NONE);
280 DBUG_RETURN(FALSE);
281 }
282
283
284 /**
285 Checks if possible to do prune partitions on insert.
286
287 @param thd Thread context
288 @param duplic How to handle duplicates
289 @param update In case of ON DUPLICATE UPDATE, default function fields
290 @param update_fields In case of ON DUPLICATE UPDATE, which fields to update
291 @param fields Listed fields
292 @param empty_values True if values is empty (only defaults)
293 @param[out] prune_needs_default_values Set on return if copying of default
294 values is needed
295 @param[out] can_prune_partitions Enum showing if possible to prune
296 @param[inout] used_partitions If possible to prune the bitmap
297 is initialized and cleared
298
299 @return Operation status
300 @retval false Success
301 @retval true Failure
302 */
303
can_prune_insert(THD * thd,enum_duplicates duplic,COPY_INFO & update,List<Item> & update_fields,List<Item> & fields,bool empty_values,enum_can_prune * can_prune_partitions,bool * prune_needs_default_values,MY_BITMAP * used_partitions)304 bool partition_info::can_prune_insert(THD* thd,
305 enum_duplicates duplic,
306 COPY_INFO &update,
307 List<Item> &update_fields,
308 List<Item> &fields,
309 bool empty_values,
310 enum_can_prune *can_prune_partitions,
311 bool *prune_needs_default_values,
312 MY_BITMAP *used_partitions)
313 {
314 uint32 *bitmap_buf;
315 uint bitmap_bytes;
316 uint num_partitions= 0;
317 *can_prune_partitions= PRUNE_NO;
318 assert(bitmaps_are_initialized);
319 DBUG_ENTER("partition_info::can_prune_insert");
320
321 if (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)
322 DBUG_RETURN(false); /* Should not insert prune NDB tables */
323
324 /*
325 If under LOCK TABLES pruning will skip start_stmt instead of external_lock
326 for unused partitions.
327
328 Cannot prune if there are BEFORE INSERT triggers that changes any
329 partitioning column, since they may change the row to be in another
330 partition.
331 */
332 if (table->triggers)
333 {
334 Trigger_chain *trigger_chain=
335 table->triggers->get_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE);
336
337 if (trigger_chain &&
338 trigger_chain->has_updated_trigger_fields(&full_part_field_set))
339 DBUG_RETURN(false);
340 }
341
342 /*
343 Can't prune partitions over generated columns, as their values are
344 calculated much later.
345 */
346 if (table->vfield)
347 {
348 Field **fld;
349 for (fld= table->vfield; *fld; fld++)
350 {
351 if (bitmap_is_set(&full_part_field_set, (*fld)->field_index))
352 DBUG_RETURN(false);
353 }
354 }
355
356 if (table->found_next_number_field)
357 {
358 /*
359 If the field is used in the partitioning expression, we cannot prune.
360 TODO: If all rows have not null values and
361 is not 0 (with NO_AUTO_VALUE_ON_ZERO sql_mode), then pruning is possible!
362 */
363 if (bitmap_is_set(&full_part_field_set,
364 table->found_next_number_field->field_index))
365 DBUG_RETURN(false);
366 }
367
368 /*
369 If updating a field in the partitioning expression, we cannot prune.
370
371 Note: TIMESTAMP_AUTO_SET_ON_INSERT is handled by converting Item_null
372 to the start time of the statement. Which will be the same as in
373 write_row(). So pruning of TIMESTAMP DEFAULT CURRENT_TIME will work.
374 But TIMESTAMP_AUTO_SET_ON_UPDATE cannot be pruned if the timestamp
375 column is a part of any part/subpart expression.
376 */
377 if (duplic == DUP_UPDATE)
378 {
379 /*
380 Cannot prune if any field in the partitioning expression can
381 be updated by ON DUPLICATE UPDATE.
382 */
383 if (update.function_defaults_apply_on_columns(&full_part_field_set))
384 DBUG_RETURN(false);
385
386 /*
387 TODO: add check for static update values, which can be pruned.
388 */
389 if (is_fields_in_part_expr(update_fields))
390 DBUG_RETURN(false);
391
392 /*
393 Cannot prune if there are BEFORE UPDATE triggers that changes any
394 partitioning column, since they may change the row to be in another
395 partition.
396 */
397 if (table->triggers)
398 {
399 Trigger_chain *trigger_chain=
400 table->triggers->get_triggers(TRG_EVENT_UPDATE, TRG_ACTION_BEFORE);
401
402 if (trigger_chain &&
403 trigger_chain->has_updated_trigger_fields(&full_part_field_set))
404 DBUG_RETURN(false);
405 }
406 }
407
408 /*
409 If not all partitioning fields are given,
410 we also must set all non given partitioning fields
411 to get correct defaults.
412 TODO: If any gain, we could enhance this by only copy the needed default
413 fields by
414 1) check which fields needs to be set.
415 2) only copy those fields from the default record.
416 */
417 *prune_needs_default_values= false;
418 if (fields.elements)
419 {
420 if (!is_full_part_expr_in_fields(fields))
421 *prune_needs_default_values= true;
422 }
423 else if (empty_values)
424 {
425 *prune_needs_default_values= true; // like 'INSERT INTO t () VALUES ()'
426 }
427 else
428 {
429 /*
430 In case of INSERT INTO t VALUES (...) we must get values for
431 all fields in table from VALUES (...) part, so no defaults
432 are needed.
433 */
434 }
435
436 /* Pruning possible, have to initialize the used_partitions bitmap. */
437 num_partitions= lock_partitions.n_bits;
438 bitmap_bytes= bitmap_buffer_size(num_partitions);
439 if (!(bitmap_buf= (uint32*) thd->alloc(bitmap_bytes)))
440 {
441 mem_alloc_error(bitmap_bytes);
442 DBUG_RETURN(true);
443 }
444 /* Also clears all bits. */
445 if (bitmap_init(used_partitions, bitmap_buf, num_partitions, false))
446 {
447 /* purecov: begin deadcode */
448 /* Cannot happen, due to pre-alloc. */
449 mem_alloc_error(bitmap_bytes);
450 DBUG_RETURN(true);
451 /* purecov: end */
452 }
453 /*
454 If no partitioning field in set (e.g. defaults) check pruning only once.
455 */
456 if (fields.elements &&
457 !is_fields_in_part_expr(fields))
458 *can_prune_partitions= PRUNE_DEFAULTS;
459 else
460 *can_prune_partitions= PRUNE_YES;
461
462 DBUG_RETURN(false);
463 }
464
465
466 /**
467 Mark the partition, the record belongs to, as used.
468
469 @param fields Fields to set
470 @param values Values to use
471 @param info COPY_INFO used for default values handling
472 @param copy_default_values True if we should copy default values
473 @param used_partitions Bitmap to set
474
475 @returns Operational status
476 @retval false Success
477 @retval true Failure
478 */
479
set_used_partition(List<Item> & fields,List<Item> & values,COPY_INFO & info,bool copy_default_values,MY_BITMAP * used_partitions)480 bool partition_info::set_used_partition(List<Item> &fields,
481 List<Item> &values,
482 COPY_INFO &info,
483 bool copy_default_values,
484 MY_BITMAP *used_partitions)
485 {
486 THD *thd= table->in_use;
487 uint32 part_id;
488 longlong func_value;
489 Dummy_error_handler error_handler;
490 bool ret= true;
491 DBUG_ENTER("set_partition");
492 assert(thd);
493
494 /* Only allow checking of constant values */
495 List_iterator_fast<Item> v(values);
496 Item *item;
497 thd->push_internal_handler(&error_handler);
498 while ((item= v++))
499 {
500 if (!item->const_item())
501 goto err;
502 }
503
504 if (copy_default_values)
505 restore_record(table,s->default_values);
506
507 if (fields.elements || !values.elements)
508 {
509 if (fill_record(thd, table, fields, values, &full_part_field_set, NULL))
510 goto err;
511 }
512 else
513 {
514 if (fill_record(thd, table, table->field, values, &full_part_field_set,
515 NULL))
516 goto err;
517 }
518 assert(!table->auto_increment_field_not_null);
519
520 /*
521 Evaluate DEFAULT functions like CURRENT_TIMESTAMP.
522 TODO: avoid setting non partitioning fields default value, to avoid
523 overhead. Not yet done, since mostly only one DEFAULT function per
524 table, or at least very few such columns.
525 */
526 if (info.function_defaults_apply_on_columns(&full_part_field_set))
527 info.set_function_defaults(table);
528
529 {
530 /*
531 This function is used in INSERT; 'values' are supplied by user,
532 or are default values, not values read from a table, so read_set is
533 irrelevant.
534 */
535 my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
536 const int rc= get_partition_id(this, &part_id, &func_value);
537 dbug_tmp_restore_column_map(table->read_set, old_map);
538 if (rc)
539 goto err;
540 }
541
542 DBUG_PRINT("info", ("Insert into partition %u", part_id));
543 bitmap_set_bit(used_partitions, part_id);
544 ret= false;
545
546 err:
547 thd->pop_internal_handler();
548 DBUG_RETURN(ret);
549 }
550
551
552 /*
553 Create a memory area where default partition names are stored and fill it
554 up with the names.
555
556 SYNOPSIS
557 create_default_partition_names()
558 part_no Partition number for subparts
559 num_parts Number of partitions
560 start_no Starting partition number
561 subpart Is it subpartitions
562
563 RETURN VALUE
564 A pointer to the memory area of the default partition names
565
566 DESCRIPTION
567 A support routine for the partition code where default values are
568 generated.
569 The external routine needing this code is check_partition_info
570 */
571
572 #define MAX_PART_NAME_SIZE 8
573
create_default_partition_names(uint part_no,uint num_parts_arg,uint start_no)574 char *partition_info::create_default_partition_names(uint part_no,
575 uint num_parts_arg,
576 uint start_no)
577 {
578 char *ptr= (char*) sql_calloc(num_parts_arg*MAX_PART_NAME_SIZE);
579 char *move_ptr= ptr;
580 uint i= 0;
581 DBUG_ENTER("create_default_partition_names");
582
583 if (likely(ptr != 0))
584 {
585 do
586 {
587 sprintf(move_ptr, "p%u", (start_no + i));
588 move_ptr+= MAX_PART_NAME_SIZE;
589 } while (++i < num_parts_arg);
590 }
591 else
592 {
593 mem_alloc_error(num_parts_arg*MAX_PART_NAME_SIZE);
594 }
595 DBUG_RETURN(ptr);
596 }
597
598
599 /*
600 Generate a version string for partition expression
601 This function must be updated every time there is a possibility for
602 a new function of a higher version number than 5.5.0.
603
604 SYNOPSIS
605 set_show_version_string()
606 RETURN VALUES
607 None
608 */
set_show_version_string(String * packet)609 void partition_info::set_show_version_string(String *packet)
610 {
611 int version= 0;
612 if (column_list)
613 packet->append(STRING_WITH_LEN("\n/*!50500"));
614 else
615 {
616 if (part_expr)
617 part_expr->walk(&Item::intro_version, Item::WALK_POSTFIX,
618 (uchar*)&version);
619 if (subpart_expr)
620 subpart_expr->walk(&Item::intro_version, Item::WALK_POSTFIX,
621 (uchar*)&version);
622 if (version == 0)
623 {
624 /* No new functions in partition function */
625 packet->append(STRING_WITH_LEN("\n/*!50100"));
626 }
627 else
628 {
629 char buf[65];
630 char *buf_ptr= longlong10_to_str((longlong)version, buf, 10);
631 packet->append(STRING_WITH_LEN("\n/*!"));
632 packet->append(buf, (size_t)(buf_ptr - buf));
633 }
634 }
635 }
636
637 /*
638 Create a unique name for the subpartition as part_name'sp''subpart_no'
639 SYNOPSIS
640 create_default_subpartition_name()
641 subpart_no Number of subpartition
642 part_name Name of partition
643 RETURN VALUES
644 >0 A reference to the created name string
645 0 Memory allocation error
646 */
647
create_default_subpartition_name(uint subpart_no,const char * part_name)648 char *partition_info::create_default_subpartition_name(uint subpart_no,
649 const char *part_name)
650 {
651 size_t size_alloc= strlen(part_name) + MAX_PART_NAME_SIZE;
652 char *ptr= (char*) sql_calloc(size_alloc);
653 DBUG_ENTER("create_default_subpartition_name");
654
655 if (likely(ptr != NULL))
656 {
657 my_snprintf(ptr, size_alloc, "%ssp%u", part_name, subpart_no);
658 }
659 else
660 {
661 mem_alloc_error(size_alloc);
662 }
663 DBUG_RETURN(ptr);
664 }
665
666
667 /*
668 Set up all the default partitions not set-up by the user in the SQL
669 statement. Also perform a number of checks that the user hasn't tried
670 to use default values where no defaults exists.
671
672 SYNOPSIS
673 set_up_default_partitions()
674 file A reference to a handler of the table
675 info Create info
676 start_no Starting partition number
677
678 RETURN VALUE
679 TRUE Error, attempted default values not possible
680 FALSE Ok, default partitions set-up
681
682 DESCRIPTION
683 The routine uses the underlying handler of the partitioning to define
684 the default number of partitions. For some handlers this requires
685 knowledge of the maximum number of rows to be stored in the table.
686 This routine only accepts HASH and KEY partitioning and thus there is
687 no subpartitioning if this routine is successful.
688 The external routine needing this code is check_partition_info
689 */
690
set_up_default_partitions(Partition_handler * part_handler,HA_CREATE_INFO * info,uint start_no)691 bool partition_info::set_up_default_partitions(Partition_handler *part_handler,
692 HA_CREATE_INFO *info,
693 uint start_no)
694 {
695 uint i;
696 char *default_name;
697 bool result= TRUE;
698 DBUG_ENTER("partition_info::set_up_default_partitions");
699
700
701 if (part_type != HASH_PARTITION)
702 {
703 const char *error_string;
704 if (part_type == RANGE_PARTITION)
705 error_string= partition_keywords[PKW_RANGE].str;
706 else
707 error_string= partition_keywords[PKW_LIST].str;
708 my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_string);
709 goto end;
710 }
711
712 if (num_parts == 0)
713 {
714 if (!part_handler)
715 {
716 num_parts= 1;
717 }
718 else
719 {
720 num_parts= part_handler->get_default_num_partitions(info);
721 }
722 if (num_parts == 0)
723 {
724 my_error(ER_PARTITION_NOT_DEFINED_ERROR, MYF(0), "partitions");
725 goto end;
726 }
727 }
728
729 if (unlikely(num_parts > MAX_PARTITIONS))
730 {
731 my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
732 goto end;
733 }
734 if (unlikely((!(default_name= create_default_partition_names(0, num_parts,
735 start_no)))))
736 goto end;
737 i= 0;
738 do
739 {
740 partition_element *part_elem= new partition_element();
741 if (likely(part_elem != 0 &&
742 (!partitions.push_back(part_elem))))
743 {
744 part_elem->engine_type= default_engine_type;
745 part_elem->partition_name= default_name;
746 default_name+=MAX_PART_NAME_SIZE;
747 }
748 else
749 {
750 mem_alloc_error(sizeof(partition_element));
751 goto end;
752 }
753 } while (++i < num_parts);
754 result= FALSE;
755 end:
756 DBUG_RETURN(result);
757 }
758
759
760 /*
761 Set up all the default subpartitions not set-up by the user in the SQL
762 statement. Also perform a number of checks that the default partitioning
763 becomes an allowed partitioning scheme.
764
765 SYNOPSIS
766 set_up_default_subpartitions()
767 file A reference to a handler of the table
768 info Create info
769
770 RETURN VALUE
771 TRUE Error, attempted default values not possible
772 FALSE Ok, default partitions set-up
773
774 DESCRIPTION
775 The routine uses the underlying handler of the partitioning to define
776 the default number of partitions. For some handlers this requires
777 knowledge of the maximum number of rows to be stored in the table.
778 This routine is only called for RANGE or LIST partitioning and those
779 need to be specified so only subpartitions are specified.
780 The external routine needing this code is check_partition_info
781 */
782
783 bool
set_up_default_subpartitions(Partition_handler * part_handler,HA_CREATE_INFO * info)784 partition_info::set_up_default_subpartitions(Partition_handler *part_handler,
785 HA_CREATE_INFO *info)
786 {
787 uint i, j;
788 bool result= TRUE;
789 partition_element *part_elem;
790 List_iterator<partition_element> part_it(partitions);
791 DBUG_ENTER("partition_info::set_up_default_subpartitions");
792
793 if (num_subparts == 0)
794 {
795 if (!part_handler)
796 {
797 num_subparts= 1;
798 }
799 else
800 {
801 num_subparts= part_handler->get_default_num_partitions(info);
802 }
803 }
804 if (unlikely((num_parts * num_subparts) > MAX_PARTITIONS))
805 {
806 my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
807 goto end;
808 }
809 i= 0;
810 do
811 {
812 part_elem= part_it++;
813 j= 0;
814 do
815 {
816 partition_element *subpart_elem= new partition_element(part_elem);
817 if (likely(subpart_elem != 0 &&
818 (!part_elem->subpartitions.push_back(subpart_elem))))
819 {
820 char *ptr= create_default_subpartition_name(j,
821 part_elem->partition_name);
822 if (!ptr)
823 goto end;
824 subpart_elem->engine_type= default_engine_type;
825 subpart_elem->partition_name= ptr;
826 }
827 else
828 {
829 mem_alloc_error(sizeof(partition_element));
830 goto end;
831 }
832 } while (++j < num_subparts);
833 } while (++i < num_parts);
834 result= FALSE;
835 end:
836 DBUG_RETURN(result);
837 }
838
839
840 /*
841 Support routine for check_partition_info
842
843 SYNOPSIS
844 set_up_defaults_for_partitioning()
845 file A reference to a handler of the table
846 info Create info
847 start_no Starting partition number
848
849 RETURN VALUE
850 TRUE Error, attempted default values not possible
851 FALSE Ok, default partitions set-up
852
853 DESCRIPTION
854 Set up defaults for partition or subpartition (cannot set-up for both,
855 this will return an error.
856 */
857
858 bool partition_info::
set_up_defaults_for_partitioning(Partition_handler * part_handler,HA_CREATE_INFO * info,uint start_no)859 set_up_defaults_for_partitioning(Partition_handler *part_handler,
860 HA_CREATE_INFO *info,
861 uint start_no)
862 {
863 DBUG_ENTER("partition_info::set_up_defaults_for_partitioning");
864
865 if (!default_partitions_setup)
866 {
867 default_partitions_setup= TRUE;
868 if (use_default_partitions)
869 DBUG_RETURN(set_up_default_partitions(part_handler, info, start_no));
870 if (is_sub_partitioned() &&
871 use_default_subpartitions)
872 DBUG_RETURN(set_up_default_subpartitions(part_handler, info));
873 }
874 DBUG_RETURN(FALSE);
875 }
876
877
878 /*
879 Support routine for check_partition_info
880
881 SYNOPSIS
882 find_duplicate_field
883 no parameters
884
885 RETURN VALUE
886 Erroneus field name Error, there are two fields with same name
887 NULL Ok, no field defined twice
888
889 DESCRIPTION
890 Check that the user haven't defined the same field twice in
891 key or column list partitioning.
892 */
find_duplicate_field()893 char* partition_info::find_duplicate_field()
894 {
895 char *field_name_outer, *field_name_inner;
896 List_iterator<char> it_outer(part_field_list);
897 uint num_fields= part_field_list.elements;
898 uint i,j;
899 DBUG_ENTER("partition_info::find_duplicate_field");
900
901 for (i= 0; i < num_fields; i++)
902 {
903 field_name_outer= it_outer++;
904 List_iterator<char> it_inner(part_field_list);
905 for (j= 0; j < num_fields; j++)
906 {
907 field_name_inner= it_inner++;
908 if (i >= j)
909 continue;
910 if (!(my_strcasecmp(system_charset_info,
911 field_name_outer,
912 field_name_inner)))
913 {
914 DBUG_RETURN(field_name_outer);
915 }
916 }
917 }
918 DBUG_RETURN(NULL);
919 }
920
921
922 /**
923 @brief Get part_elem and part_id from partition name
924
925 @param partition_name Name of partition to search for.
926 @param file_name[out] Partition file name (part after table name,
927 #P#<part>[#SP#<subpart>]), skipped if NULL.
928 @param part_id[out] Id of found partition or NOT_A_PARTITION_ID.
929
930 @retval Pointer to part_elem of [sub]partition, if not found NULL
931
932 @note Since names of partitions AND subpartitions must be unique,
933 this function searches both partitions and subpartitions and if name of
934 a partition is given for a subpartitioned table, part_elem will be
935 the partition, but part_id will be NOT_A_PARTITION_ID and file_name not set.
936 */
get_part_elem(const char * partition_name,char * file_name,uint32 * part_id)937 partition_element *partition_info::get_part_elem(const char *partition_name,
938 char *file_name,
939 uint32 *part_id)
940 {
941 List_iterator<partition_element> part_it(partitions);
942 uint i= 0;
943 DBUG_ENTER("partition_info::get_part_elem");
944 assert(part_id);
945 *part_id= NOT_A_PARTITION_ID;
946 do
947 {
948 partition_element *part_elem= part_it++;
949 if (is_sub_partitioned())
950 {
951 List_iterator<partition_element> sub_part_it(part_elem->subpartitions);
952 uint j= 0;
953 do
954 {
955 partition_element *sub_part_elem= sub_part_it++;
956 if (!my_strcasecmp(system_charset_info,
957 sub_part_elem->partition_name, partition_name))
958 {
959 if (file_name)
960 create_subpartition_name(file_name, "",
961 part_elem->partition_name,
962 partition_name,
963 NORMAL_PART_NAME);
964 *part_id= j + (i * num_subparts);
965 DBUG_RETURN(sub_part_elem);
966 }
967 } while (++j < num_subparts);
968
969 /* Naming a partition (first level) on a subpartitioned table. */
970 if (!my_strcasecmp(system_charset_info,
971 part_elem->partition_name, partition_name))
972 DBUG_RETURN(part_elem);
973 }
974 else if (!my_strcasecmp(system_charset_info,
975 part_elem->partition_name, partition_name))
976 {
977 if (file_name)
978 create_partition_name(file_name, "", partition_name,
979 NORMAL_PART_NAME, TRUE);
980 *part_id= i;
981 DBUG_RETURN(part_elem);
982 }
983 } while (++i < num_parts);
984 DBUG_RETURN(NULL);
985 }
986
987
988 /**
989 Helper function to find_duplicate_name.
990 */
991
get_part_name_from_elem(const char * name,size_t * length,my_bool not_used MY_ATTRIBUTE ((unused)))992 static const char *get_part_name_from_elem(const char *name, size_t *length,
993 my_bool not_used MY_ATTRIBUTE((unused)))
994 {
995 *length= strlen(name);
996 return name;
997 }
998
999 /*
1000 A support function to check partition names for duplication in a
1001 partitioned table
1002
1003 SYNOPSIS
1004 find_duplicate_name()
1005
1006 RETURN VALUES
1007 NULL Has unique part and subpart names
1008 !NULL Pointer to duplicated name
1009
1010 DESCRIPTION
1011 Checks that the list of names in the partitions doesn't contain any
1012 duplicated names.
1013 */
1014
find_duplicate_name()1015 char *partition_info::find_duplicate_name()
1016 {
1017 HASH partition_names;
1018 uint max_names;
1019 const uchar *curr_name= NULL;
1020 List_iterator<partition_element> parts_it(partitions);
1021 partition_element *p_elem;
1022
1023 DBUG_ENTER("partition_info::find_duplicate_name");
1024
1025 /*
1026 TODO: If table->s->ha_part_data->partition_name_hash.elements is > 0,
1027 then we could just return NULL, but that has not been verified.
1028 And this only happens when in ALTER TABLE with full table copy.
1029 */
1030
1031 max_names= num_parts;
1032 if (is_sub_partitioned())
1033 max_names+= num_parts * num_subparts;
1034 if (my_hash_init(&partition_names, system_charset_info, max_names, 0, 0,
1035 (my_hash_get_key) get_part_name_from_elem, 0, HASH_UNIQUE,
1036 PSI_INSTRUMENT_ME))
1037 {
1038 assert(0);
1039 curr_name= (const uchar*) "Internal failure";
1040 goto error;
1041 }
1042 while ((p_elem= (parts_it++)))
1043 {
1044 curr_name= (const uchar*) p_elem->partition_name;
1045 if (my_hash_insert(&partition_names, curr_name))
1046 goto error;
1047
1048 if (!p_elem->subpartitions.is_empty())
1049 {
1050 List_iterator<partition_element> subparts_it(p_elem->subpartitions);
1051 partition_element *subp_elem;
1052 while ((subp_elem= (subparts_it++)))
1053 {
1054 curr_name= (const uchar*) subp_elem->partition_name;
1055 if (my_hash_insert(&partition_names, curr_name))
1056 goto error;
1057 }
1058 }
1059 }
1060 my_hash_free(&partition_names);
1061 DBUG_RETURN(NULL);
1062 error:
1063 my_hash_free(&partition_names);
1064 DBUG_RETURN((char*) curr_name);
1065 }
1066
1067
1068 /*
1069 Check that the partition/subpartition is setup to use the correct
1070 storage engine
1071 SYNOPSIS
1072 check_engine_condition()
1073 p_elem Partition element
1074 table_engine_set Have user specified engine on table level
1075 inout::engine_type Current engine used
1076 inout::first Is it first partition
1077 RETURN VALUE
1078 TRUE Failed check
1079 FALSE Ok
1080 DESCRIPTION
1081 Specified engine for table and partitions p0 and pn
1082 Must be correct both on CREATE and ALTER commands
1083 table p0 pn res (0 - OK, 1 - FAIL)
1084 - - - 0
1085 - - x 1
1086 - x - 1
1087 - x x 0
1088 x - - 0
1089 x - x 0
1090 x x - 0
1091 x x x 0
1092 i.e:
1093 - All subpartitions must use the same engine
1094 AND it must be the same as the partition.
1095 - All partitions must use the same engine
1096 AND it must be the same as the table.
1097 - if one does NOT specify an engine on the table level
1098 then one must either NOT specify any engine on any
1099 partition/subpartition OR for ALL partitions/subpartitions
1100 Note:
1101 When ALTER a table, the engines are already set for all levels
1102 (table, all partitions and subpartitions). So if one want to
1103 change the storage engine, one must specify it on the table level
1104
1105 */
1106
check_engine_condition(partition_element * p_elem,bool table_engine_set,handlerton ** engine_type,bool * first)1107 static bool check_engine_condition(partition_element *p_elem,
1108 bool table_engine_set,
1109 handlerton **engine_type,
1110 bool *first)
1111 {
1112 DBUG_ENTER("check_engine_condition");
1113
1114 DBUG_PRINT("enter", ("p_eng %s t_eng %s t_eng_set %u first %u state %u",
1115 ha_resolve_storage_engine_name(p_elem->engine_type),
1116 ha_resolve_storage_engine_name(*engine_type),
1117 table_engine_set, *first, p_elem->part_state));
1118 if (*first && !table_engine_set)
1119 {
1120 *engine_type= p_elem->engine_type;
1121 DBUG_PRINT("info", ("setting table_engine = %s",
1122 ha_resolve_storage_engine_name(*engine_type)));
1123 }
1124 *first= FALSE;
1125 if ((table_engine_set &&
1126 (p_elem->engine_type != (*engine_type) &&
1127 p_elem->engine_type)) ||
1128 (!table_engine_set &&
1129 p_elem->engine_type != (*engine_type)))
1130 {
1131 DBUG_RETURN(TRUE);
1132 }
1133
1134 DBUG_RETURN(FALSE);
1135 }
1136
1137
1138 /*
1139 Check engine mix that it is correct
1140 Current limitation is that all partitions and subpartitions
1141 must use the same storage engine.
1142 SYNOPSIS
1143 check_engine_mix()
1144 inout::engine_type Current engine used
1145 table_engine_set Have user specified engine on table level
1146 RETURN VALUE
1147 TRUE Error, mixed engines
1148 FALSE Ok, no mixed engines
1149 DESCRIPTION
1150 Current check verifies only that all handlers are the same.
1151 Later this check will be more sophisticated.
1152 (specified partition handler ) specified table handler
1153 (NDB, NDB) NDB OK
1154 (MYISAM, MYISAM) - OK
1155 (MYISAM, -) - NOT OK
1156 (MYISAM, -) MYISAM OK
1157 (- , MYISAM) - NOT OK
1158 (- , -) MYISAM OK
1159 (-,-) - OK
1160 (NDB, MYISAM) * NOT OK
1161 */
1162
check_engine_mix(handlerton * engine_type,bool table_engine_set)1163 bool partition_info::check_engine_mix(handlerton *engine_type,
1164 bool table_engine_set)
1165 {
1166 handlerton *old_engine_type= engine_type;
1167 bool first= TRUE;
1168 uint n_parts= partitions.elements;
1169 DBUG_ENTER("partition_info::check_engine_mix");
1170 DBUG_PRINT("info", ("in: engine_type = %s, table_engine_set = %u",
1171 ha_resolve_storage_engine_name(engine_type),
1172 table_engine_set));
1173 if (n_parts)
1174 {
1175 List_iterator<partition_element> part_it(partitions);
1176 uint i= 0;
1177 do
1178 {
1179 partition_element *part_elem= part_it++;
1180 DBUG_PRINT("info", ("part = %d engine = %s table_engine_set %u",
1181 i, ha_resolve_storage_engine_name(part_elem->engine_type),
1182 table_engine_set));
1183 if (is_sub_partitioned() &&
1184 part_elem->subpartitions.elements)
1185 {
1186 uint n_subparts= part_elem->subpartitions.elements;
1187 uint j= 0;
1188 List_iterator<partition_element> sub_it(part_elem->subpartitions);
1189 do
1190 {
1191 partition_element *sub_elem= sub_it++;
1192 DBUG_PRINT("info", ("sub = %d engine = %s table_engie_set %u",
1193 j, ha_resolve_storage_engine_name(sub_elem->engine_type),
1194 table_engine_set));
1195 if (check_engine_condition(sub_elem, table_engine_set,
1196 &engine_type, &first))
1197 goto error;
1198 } while (++j < n_subparts);
1199 /* ensure that the partition also has correct engine */
1200 if (check_engine_condition(part_elem, table_engine_set,
1201 &engine_type, &first))
1202 goto error;
1203 }
1204 else if (check_engine_condition(part_elem, table_engine_set,
1205 &engine_type, &first))
1206 goto error;
1207 } while (++i < n_parts);
1208 }
1209 DBUG_PRINT("info", ("engine_type = %s",
1210 ha_resolve_storage_engine_name(engine_type)));
1211 if (!engine_type)
1212 engine_type= old_engine_type;
1213 if (engine_type->flags & HTON_NO_PARTITION)
1214 {
1215 my_error(ER_PARTITION_MERGE_ERROR, MYF(0));
1216 DBUG_RETURN(TRUE);
1217 }
1218 DBUG_PRINT("info", ("out: engine_type = %s",
1219 ha_resolve_storage_engine_name(engine_type)));
1220 assert(!is_ha_partition_handlerton(engine_type));
1221 DBUG_RETURN(FALSE);
1222 error:
1223 /*
1224 Mixed engines not yet supported but when supported it will need
1225 the partition handler
1226 */
1227 DBUG_RETURN(TRUE);
1228 }
1229
1230
1231 /*
1232 This routine allocates an array for all range constants to achieve a fast
1233 check what partition a certain value belongs to. At the same time it does
1234 also check that the range constants are defined in increasing order and
1235 that the expressions are constant integer expressions.
1236
1237 SYNOPSIS
1238 check_range_constants()
1239 thd Thread object
1240
1241 RETURN VALUE
1242 TRUE An error occurred during creation of range constants
1243 FALSE Successful creation of range constant mapping
1244
1245 DESCRIPTION
1246 This routine is called from check_partition_info to get a quick error
1247 before we came too far into the CREATE TABLE process. It is also called
1248 from fix_partition_func every time we open the .frm file. It is only
1249 called for RANGE PARTITIONed tables.
1250 */
1251
check_range_constants(THD * thd)1252 bool partition_info::check_range_constants(THD *thd)
1253 {
1254 partition_element* part_def;
1255 bool first= TRUE;
1256 uint i;
1257 List_iterator<partition_element> it(partitions);
1258 int result= TRUE;
1259 DBUG_ENTER("partition_info::check_range_constants");
1260 DBUG_PRINT("enter", ("RANGE with %d parts, column_list = %u", num_parts,
1261 column_list));
1262
1263 if (column_list)
1264 {
1265 part_column_list_val *loc_range_col_array;
1266 part_column_list_val *current_largest_col_val= NULL;
1267 uint num_column_values= part_field_list.elements;
1268 uint size_entries= sizeof(part_column_list_val) * num_column_values;
1269 range_col_array= (part_column_list_val*)sql_calloc(num_parts *
1270 size_entries);
1271 if (unlikely(range_col_array == NULL))
1272 {
1273 mem_alloc_error(num_parts * size_entries);
1274 goto end;
1275 }
1276 loc_range_col_array= range_col_array;
1277 i= 0;
1278 do
1279 {
1280 part_def= it++;
1281 {
1282 List_iterator<part_elem_value> list_val_it(part_def->list_val_list);
1283 part_elem_value *range_val= list_val_it++;
1284 part_column_list_val *col_val= range_val->col_val_array;
1285 assert(part_def->list_val_list.elements == 1);
1286
1287 if (fix_column_value_functions(thd, range_val, i))
1288 goto end;
1289 memcpy(loc_range_col_array, (const void*)col_val, size_entries);
1290 loc_range_col_array+= num_column_values;
1291 if (!first)
1292 {
1293 if (compare_column_values((const void*)current_largest_col_val,
1294 (const void*)col_val) >= 0)
1295 goto range_not_increasing_error;
1296 }
1297 current_largest_col_val= col_val;
1298 }
1299 first= FALSE;
1300 } while (++i < num_parts);
1301 }
1302 else
1303 {
1304 longlong current_largest= 0;
1305 longlong part_range_value;
1306 bool signed_flag= !part_expr->unsigned_flag;
1307
1308 range_int_array= (longlong*)sql_alloc(num_parts * sizeof(longlong));
1309 if (unlikely(range_int_array == NULL))
1310 {
1311 mem_alloc_error(num_parts * sizeof(longlong));
1312 goto end;
1313 }
1314 i= 0;
1315 do
1316 {
1317 part_def= it++;
1318 if ((i != (num_parts - 1)) || !defined_max_value)
1319 {
1320 part_range_value= part_def->range_value;
1321 if (!signed_flag)
1322 part_range_value-= 0x8000000000000000ULL;
1323 }
1324 else
1325 part_range_value= LLONG_MAX;
1326
1327 if (!first)
1328 {
1329 if (unlikely(current_largest > part_range_value) ||
1330 (unlikely(current_largest == part_range_value) &&
1331 (part_range_value < LLONG_MAX ||
1332 i != (num_parts - 1) ||
1333 !defined_max_value)))
1334 goto range_not_increasing_error;
1335 }
1336 range_int_array[i]= part_range_value;
1337 current_largest= part_range_value;
1338 first= FALSE;
1339 } while (++i < num_parts);
1340 }
1341 result= FALSE;
1342 end:
1343 DBUG_RETURN(result);
1344
1345 range_not_increasing_error:
1346 my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0));
1347 goto end;
1348 }
1349
1350
1351 /*
1352 Support routines for check_list_constants used by qsort to sort the
1353 constant list expressions. One routine for integers and one for
1354 column lists.
1355
1356 SYNOPSIS
1357 list_part_cmp()
1358 a First list constant to compare with
1359 b Second list constant to compare with
1360
1361 RETURN VALUE
1362 +1 a > b
1363 0 a == b
1364 -1 a < b
1365 */
1366
1367 extern "C"
partition_info_list_part_cmp(const void * a,const void * b)1368 int partition_info_list_part_cmp(const void* a, const void* b)
1369 {
1370 longlong a1= ((LIST_PART_ENTRY*)a)->list_value;
1371 longlong b1= ((LIST_PART_ENTRY*)b)->list_value;
1372 if (a1 < b1)
1373 return -1;
1374 else if (a1 > b1)
1375 return +1;
1376 else
1377 return 0;
1378 }
1379
1380
list_part_cmp(const void * a,const void * b)1381 int partition_info::list_part_cmp(const void* a, const void* b)
1382 {
1383 return partition_info_list_part_cmp(a, b);
1384 }
1385
1386
1387 /*
1388 Compare two lists of column values in RANGE/LIST partitioning
1389 SYNOPSIS
1390 compare_column_values()
1391 first First column list argument
1392 second Second column list argument
1393 RETURN VALUES
1394 0 Equal
1395 -1 First argument is smaller
1396 +1 First argument is larger
1397 */
1398
1399 extern "C"
partition_info_compare_column_values(const void * first_arg,const void * second_arg)1400 int partition_info_compare_column_values(const void *first_arg,
1401 const void *second_arg)
1402 {
1403 const part_column_list_val *first= (part_column_list_val*)first_arg;
1404 const part_column_list_val *second= (part_column_list_val*)second_arg;
1405 partition_info *part_info= first->part_info;
1406 Field **field;
1407
1408 for (field= part_info->part_field_array; *field;
1409 field++, first++, second++)
1410 {
1411 if (first->max_value || second->max_value)
1412 {
1413 if (first->max_value && second->max_value)
1414 return 0;
1415 if (second->max_value)
1416 return -1;
1417 else
1418 return +1;
1419 }
1420 if (first->null_value || second->null_value)
1421 {
1422 if (first->null_value && second->null_value)
1423 continue;
1424 if (second->null_value)
1425 return +1;
1426 else
1427 return -1;
1428 }
1429 int res= (*field)->cmp((const uchar*)first->column_value,
1430 (const uchar*)second->column_value);
1431 if (res)
1432 return res;
1433 }
1434 return 0;
1435 }
1436
1437
compare_column_values(const void * first_arg,const void * second_arg)1438 int partition_info::compare_column_values(const void *first_arg,
1439 const void *second_arg)
1440 {
1441 return partition_info_compare_column_values(first_arg, second_arg);
1442 }
1443
1444
1445 /*
1446 This routine allocates an array for all list constants to achieve a fast
1447 check what partition a certain value belongs to. At the same time it does
1448 also check that there are no duplicates among the list constants and that
1449 that the list expressions are constant integer expressions.
1450
1451 SYNOPSIS
1452 check_list_constants()
1453 thd Thread object
1454
1455 RETURN VALUE
1456 TRUE An error occurred during creation of list constants
1457 FALSE Successful creation of list constant mapping
1458
1459 DESCRIPTION
1460 This routine is called from check_partition_info to get a quick error
1461 before we came too far into the CREATE TABLE process. It is also called
1462 from fix_partition_func every time we open the .frm file. It is only
1463 called for LIST PARTITIONed tables.
1464 */
1465
check_list_constants(THD * thd)1466 bool partition_info::check_list_constants(THD *thd)
1467 {
1468 uint i, size_entries, num_column_values;
1469 uint list_index= 0;
1470 part_elem_value *list_value;
1471 bool result= TRUE;
1472 longlong type_add, calc_value;
1473 void *curr_value;
1474 void *prev_value= NULL;
1475 partition_element* part_def;
1476 bool found_null= FALSE;
1477 qsort_cmp compare_func;
1478 void *ptr;
1479 List_iterator<partition_element> list_func_it(partitions);
1480 DBUG_ENTER("partition_info::check_list_constants");
1481
1482 num_list_values= 0;
1483 /*
1484 We begin by calculating the number of list values that have been
1485 defined in the first step.
1486
1487 We use this number to allocate a properly sized array of structs
1488 to keep the partition id and the value to use in that partition.
1489 In the second traversal we assign them values in the struct array.
1490
1491 Finally we sort the array of structs in order of values to enable
1492 a quick binary search for the proper value to discover the
1493 partition id.
1494 After sorting the array we check that there are no duplicates in the
1495 list.
1496 */
1497
1498 i= 0;
1499 do
1500 {
1501 part_def= list_func_it++;
1502 if (part_def->has_null_value)
1503 {
1504 if (found_null)
1505 {
1506 my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
1507 goto end;
1508 }
1509 has_null_value= TRUE;
1510 has_null_part_id= i;
1511 found_null= TRUE;
1512 }
1513 List_iterator<part_elem_value> list_val_it1(part_def->list_val_list);
1514 while (list_val_it1++)
1515 num_list_values++;
1516 } while (++i < num_parts);
1517 list_func_it.rewind();
1518 num_column_values= part_field_list.elements;
1519 size_entries= column_list ?
1520 (num_column_values * sizeof(part_column_list_val)) :
1521 sizeof(LIST_PART_ENTRY);
1522 ptr= sql_calloc((num_list_values+1) * size_entries);
1523 if (unlikely(ptr == NULL))
1524 {
1525 mem_alloc_error(num_list_values * size_entries);
1526 goto end;
1527 }
1528 if (column_list)
1529 {
1530 part_column_list_val *loc_list_col_array;
1531 loc_list_col_array= (part_column_list_val*)ptr;
1532 list_col_array= (part_column_list_val*)ptr;
1533 compare_func= partition_info_compare_column_values;
1534 i= 0;
1535 do
1536 {
1537 part_def= list_func_it++;
1538 List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
1539 while ((list_value= list_val_it2++))
1540 {
1541 part_column_list_val *col_val= list_value->col_val_array;
1542 if (unlikely(fix_column_value_functions(thd, list_value, i)))
1543 {
1544 DBUG_RETURN(TRUE);
1545 }
1546 memcpy(loc_list_col_array, (const void*)col_val, size_entries);
1547 loc_list_col_array+= num_column_values;
1548 }
1549 } while (++i < num_parts);
1550 }
1551 else
1552 {
1553 compare_func= partition_info_list_part_cmp;
1554 list_array= (LIST_PART_ENTRY*)ptr;
1555 i= 0;
1556 /*
1557 Fix to be able to reuse signed sort functions also for unsigned
1558 partition functions.
1559 */
1560 type_add= (longlong)(part_expr->unsigned_flag ?
1561 0x8000000000000000ULL :
1562 0ULL);
1563
1564 do
1565 {
1566 part_def= list_func_it++;
1567 List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
1568 while ((list_value= list_val_it2++))
1569 {
1570 calc_value= list_value->value - type_add;
1571 list_array[list_index].list_value= calc_value;
1572 list_array[list_index++].partition_id= i;
1573 }
1574 } while (++i < num_parts);
1575 }
1576 assert(fixed);
1577 if (num_list_values)
1578 {
1579 bool first= TRUE;
1580 /*
1581 list_array and list_col_array are unions, so this works for both
1582 variants of LIST partitioning.
1583 */
1584 my_qsort((void*)list_array, num_list_values, size_entries,
1585 compare_func);
1586
1587 i= 0;
1588 do
1589 {
1590 assert(i < num_list_values);
1591 curr_value= column_list ? (void*)&list_col_array[num_column_values * i] :
1592 (void*)&list_array[i];
1593 if (likely(first || compare_func(curr_value, prev_value)))
1594 {
1595 prev_value= curr_value;
1596 first= FALSE;
1597 }
1598 else
1599 {
1600 my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
1601 goto end;
1602 }
1603 } while (++i < num_list_values);
1604 }
1605 result= FALSE;
1606 end:
1607 DBUG_RETURN(result);
1608 }
1609
1610 /**
1611 Check if we allow DATA/INDEX DIRECTORY, if not warn and set them to NULL.
1612
1613 @param thd THD also containing sql_mode (looks from MODE_NO_DIR_IN_CREATE).
1614 @param part_elem partition_element to check.
1615 */
warn_if_dir_in_part_elem(THD * thd,partition_element * part_elem)1616 static void warn_if_dir_in_part_elem(THD *thd, partition_element *part_elem)
1617 {
1618 if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
1619 {
1620 if (part_elem->data_file_name)
1621 push_warning_printf(thd, Sql_condition::SL_WARNING,
1622 WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
1623 "DATA DIRECTORY");
1624 if (part_elem->index_file_name)
1625 push_warning_printf(thd, Sql_condition::SL_WARNING,
1626 WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
1627 "INDEX DIRECTORY");
1628 part_elem->data_file_name= part_elem->index_file_name= NULL;
1629 }
1630 }
1631
1632
1633 /*
1634 This code is used early in the CREATE TABLE and ALTER TABLE process.
1635
1636 SYNOPSIS
1637 check_partition_info()
1638 thd Thread object
1639 eng_type Return value for used engine in partitions
1640 file A reference to a handler of the table
1641 info Create info
1642 add_or_reorg_part Is it ALTER TABLE ADD/REORGANIZE command
1643
1644 RETURN VALUE
1645 TRUE Error, something went wrong
1646 FALSE Ok, full partition data structures are now generated
1647
1648 DESCRIPTION
1649 We will check that the partition info requested is possible to set-up in
1650 this version. This routine is an extension of the parser one could say.
1651 If defaults were used we will generate default data structures for all
1652 partitions.
1653
1654 */
1655
check_partition_info(THD * thd,handlerton ** eng_type,handler * file,HA_CREATE_INFO * info,bool add_or_reorg_part)1656 bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
1657 handler *file, HA_CREATE_INFO *info,
1658 bool add_or_reorg_part)
1659 {
1660 handlerton *table_engine= default_engine_type;
1661 uint i, tot_partitions;
1662 bool result= TRUE, table_engine_set;
1663 char *same_name;
1664 DBUG_ENTER("partition_info::check_partition_info");
1665 assert(!is_ha_partition_handlerton(table_engine));
1666
1667 DBUG_PRINT("info", ("default table_engine = %s",
1668 ha_resolve_storage_engine_name(table_engine)));
1669 if (!add_or_reorg_part)
1670 {
1671 int err= 0;
1672
1673 /* Check for partition expression. */
1674 if (!list_of_part_fields)
1675 {
1676 assert(part_expr);
1677 err= part_expr->walk(&Item::check_partition_func_processor,
1678 Item::WALK_POSTFIX, NULL);
1679 }
1680
1681 /* Check for sub partition expression. */
1682 if (!err && is_sub_partitioned() && !list_of_subpart_fields)
1683 {
1684 assert(subpart_expr);
1685 err= subpart_expr->walk(&Item::check_partition_func_processor,
1686 Item::WALK_POSTFIX, NULL);
1687 }
1688
1689 if (err)
1690 {
1691 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
1692 goto end;
1693 }
1694 if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
1695 fix_parser_data(thd))
1696 goto end;
1697 }
1698 if (unlikely(!is_sub_partitioned() &&
1699 !(use_default_subpartitions && use_default_num_subpartitions)))
1700 {
1701 my_error(ER_SUBPARTITION_ERROR, MYF(0));
1702 goto end;
1703 }
1704 if (unlikely(is_sub_partitioned() &&
1705 (!(part_type == RANGE_PARTITION ||
1706 part_type == LIST_PARTITION))))
1707 {
1708 /* Only RANGE and LIST partitioning can be subpartitioned */
1709 my_error(ER_SUBPARTITION_ERROR, MYF(0));
1710 goto end;
1711 }
1712 if (unlikely(set_up_defaults_for_partitioning(file->get_partition_handler(),
1713 info,
1714 (uint)0)))
1715 {
1716 goto end;
1717 }
1718 if (!(tot_partitions= get_tot_partitions()))
1719 {
1720 my_error(ER_PARTITION_NOT_DEFINED_ERROR, MYF(0), "partitions");
1721 goto end;
1722 }
1723 if (unlikely(tot_partitions > MAX_PARTITIONS))
1724 {
1725 my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
1726 goto end;
1727 }
1728 /*
1729 if NOT specified ENGINE = <engine>:
1730 If Create, always use create_info->db_type
1731 else, use previous tables db_type
1732 either ALL or NONE partition should be set to
1733 default_engine_type when not table_engine_set
1734 Note: after a table is created its storage engines for
1735 the table and all partitions/subpartitions are set.
1736 So when ALTER it is already set on table level
1737 */
1738 if (info && info->used_fields & HA_CREATE_USED_ENGINE)
1739 {
1740 table_engine_set= TRUE;
1741 table_engine= info->db_type;
1742 /* if partition hton, use thd->lex->create_info */
1743 if (is_ha_partition_handlerton(table_engine))
1744 {
1745 table_engine= thd->lex->create_info.db_type;
1746 }
1747 assert(!is_ha_partition_handlerton(table_engine));
1748 DBUG_PRINT("info", ("Using table_engine = %s",
1749 ha_resolve_storage_engine_name(table_engine)));
1750 }
1751 else
1752 {
1753 table_engine_set= FALSE;
1754 if (thd->lex->sql_command != SQLCOM_CREATE_TABLE)
1755 {
1756 table_engine_set= TRUE;
1757 DBUG_PRINT("info", ("No create, table_engine = %s",
1758 ha_resolve_storage_engine_name(table_engine)));
1759 assert(table_engine &&
1760 !is_ha_partition_handlerton(table_engine));
1761 }
1762 }
1763
1764 if (part_field_list.elements > 0 &&
1765 (same_name= find_duplicate_field()))
1766 {
1767 my_error(ER_SAME_NAME_PARTITION_FIELD, MYF(0), same_name);
1768 goto end;
1769 }
1770 if ((same_name= find_duplicate_name()))
1771 {
1772 my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
1773 goto end;
1774 }
1775 i= 0;
1776 {
1777 List_iterator<partition_element> part_it(partitions);
1778 uint num_parts_not_set= 0;
1779 uint prev_num_subparts_not_set= num_subparts + 1;
1780 do
1781 {
1782 partition_element *part_elem= part_it++;
1783 warn_if_dir_in_part_elem(thd, part_elem);
1784 if (!is_sub_partitioned())
1785 {
1786 if (part_elem->engine_type == NULL)
1787 {
1788 num_parts_not_set++;
1789 part_elem->engine_type= default_engine_type;
1790 }
1791 enum_ident_name_check ident_check_status=
1792 check_table_name(part_elem->partition_name,
1793 strlen(part_elem->partition_name), FALSE);
1794 if (ident_check_status == IDENT_NAME_WRONG)
1795 {
1796 my_error(ER_WRONG_PARTITION_NAME, MYF(0));
1797 goto end;
1798 }
1799 else if (ident_check_status == IDENT_NAME_TOO_LONG)
1800 {
1801 my_error(ER_TOO_LONG_IDENT, MYF(0));
1802 goto end;
1803 }
1804 DBUG_PRINT("info", ("part = %d engine = %s",
1805 i, ha_resolve_storage_engine_name(part_elem->engine_type)));
1806 }
1807 else
1808 {
1809 uint j= 0;
1810 uint num_subparts_not_set= 0;
1811 List_iterator<partition_element> sub_it(part_elem->subpartitions);
1812 partition_element *sub_elem;
1813 do
1814 {
1815 sub_elem= sub_it++;
1816 warn_if_dir_in_part_elem(thd, sub_elem);
1817 enum_ident_name_check ident_check_status=
1818 check_table_name(sub_elem->partition_name,
1819 strlen(sub_elem->partition_name), FALSE);
1820 if (ident_check_status == IDENT_NAME_WRONG)
1821 {
1822 my_error(ER_WRONG_PARTITION_NAME, MYF(0));
1823 goto end;
1824 }
1825 else if (ident_check_status == IDENT_NAME_TOO_LONG)
1826 {
1827 my_error(ER_TOO_LONG_IDENT, MYF(0));
1828 goto end;
1829 }
1830 if (sub_elem->engine_type == NULL)
1831 {
1832 if (part_elem->engine_type != NULL)
1833 sub_elem->engine_type= part_elem->engine_type;
1834 else
1835 {
1836 sub_elem->engine_type= default_engine_type;
1837 num_subparts_not_set++;
1838 }
1839 }
1840 DBUG_PRINT("info", ("part = %d sub = %d engine = %s", i, j,
1841 ha_resolve_storage_engine_name(sub_elem->engine_type)));
1842 } while (++j < num_subparts);
1843
1844 if (prev_num_subparts_not_set == (num_subparts + 1) &&
1845 (num_subparts_not_set == 0 ||
1846 num_subparts_not_set == num_subparts))
1847 prev_num_subparts_not_set= num_subparts_not_set;
1848
1849 if (!table_engine_set &&
1850 prev_num_subparts_not_set != num_subparts_not_set)
1851 {
1852 DBUG_PRINT("info", ("num_subparts_not_set = %u num_subparts = %u",
1853 num_subparts_not_set, num_subparts));
1854 my_error(ER_MIX_HANDLER_ERROR, MYF(0));
1855 goto end;
1856 }
1857
1858 if (part_elem->engine_type == NULL)
1859 {
1860 if (num_subparts_not_set == 0)
1861 part_elem->engine_type= sub_elem->engine_type;
1862 else
1863 {
1864 num_parts_not_set++;
1865 part_elem->engine_type= default_engine_type;
1866 }
1867 }
1868 }
1869 } while (++i < num_parts);
1870 if (!table_engine_set &&
1871 num_parts_not_set != 0 &&
1872 num_parts_not_set != num_parts)
1873 {
1874 DBUG_PRINT("info", ("num_parts_not_set = %u num_parts = %u",
1875 num_parts_not_set, num_subparts));
1876 my_error(ER_MIX_HANDLER_ERROR, MYF(0));
1877 goto end;
1878 }
1879 }
1880 if (unlikely(check_engine_mix(table_engine, table_engine_set)))
1881 {
1882 my_error(ER_MIX_HANDLER_ERROR, MYF(0));
1883 goto end;
1884 }
1885
1886 assert(table_engine == default_engine_type &&
1887 !is_ha_partition_handlerton(table_engine));
1888 if (eng_type)
1889 *eng_type= table_engine;
1890
1891
1892 /*
1893 We need to check all constant expressions that they are of the correct
1894 type and that they are increasing for ranges and not overlapping for
1895 list constants.
1896 */
1897
1898 if (add_or_reorg_part)
1899 {
1900 if (unlikely((part_type == RANGE_PARTITION &&
1901 check_range_constants(thd)) ||
1902 (part_type == LIST_PARTITION &&
1903 check_list_constants(thd))))
1904 goto end;
1905 }
1906 result= FALSE;
1907 end:
1908 DBUG_RETURN(result);
1909 }
1910
1911
1912 /*
1913 Print error for no partition found
1914
1915 SYNOPSIS
1916 print_no_partition_found()
1917 table Table object
1918
1919 RETURN VALUES
1920 */
1921
print_no_partition_found(TABLE * table_arg)1922 void partition_info::print_no_partition_found(TABLE *table_arg)
1923 {
1924 char buf[100];
1925 char *buf_ptr= (char*)&buf;
1926 TABLE_LIST table_list;
1927
1928 table_list.db= table_arg->s->db.str;
1929 table_list.table_name= table_arg->s->table_name.str;
1930
1931 if (check_single_table_access(current_thd,
1932 SELECT_ACL, &table_list, TRUE))
1933 {
1934 my_message(ER_NO_PARTITION_FOR_GIVEN_VALUE,
1935 ER(ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT), MYF(0));
1936 }
1937 else
1938 {
1939 if (column_list)
1940 buf_ptr= (char*)"from column_list";
1941 else
1942 {
1943 my_bitmap_map *old_map= dbug_tmp_use_all_columns(table_arg, table_arg->read_set);
1944 if (part_expr->null_value)
1945 buf_ptr= (char*)"NULL";
1946 else
1947 longlong2str(err_value, buf,
1948 part_expr->unsigned_flag ? 10 : -10);
1949 dbug_tmp_restore_column_map(table_arg->read_set, old_map);
1950 }
1951 my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf_ptr);
1952 }
1953 }
1954
1955
1956 /*
1957 Set fields related to partition expression
1958 SYNOPSIS
1959 set_part_expr()
1960 start_token Start of partition function string
1961 item_ptr Pointer to item tree
1962 end_token End of partition function string
1963 is_subpart Subpartition indicator
1964 RETURN VALUES
1965 TRUE Memory allocation error
1966 FALSE Success
1967 */
1968
set_part_expr(char * start_token,Item * item_ptr,char * end_token,bool is_subpart)1969 bool partition_info::set_part_expr(char *start_token, Item *item_ptr,
1970 char *end_token, bool is_subpart)
1971 {
1972 size_t expr_len= end_token - start_token;
1973 char *func_string= (char*) sql_memdup(start_token, expr_len);
1974
1975 if (!func_string)
1976 {
1977 mem_alloc_error(expr_len);
1978 return TRUE;
1979 }
1980 if (is_subpart)
1981 {
1982 list_of_subpart_fields= FALSE;
1983 subpart_expr= item_ptr;
1984 subpart_func_string= func_string;
1985 subpart_func_len= expr_len;
1986 }
1987 else
1988 {
1989 list_of_part_fields= FALSE;
1990 part_expr= item_ptr;
1991 part_func_string= func_string;
1992 part_func_len= expr_len;
1993 }
1994 return FALSE;
1995 }
1996
1997
1998 /*
1999 Check that partition fields and subpartition fields are not too long
2000
2001 SYNOPSIS
2002 check_partition_field_length()
2003
2004 RETURN VALUES
2005 TRUE Total length was too big
2006 FALSE Length is ok
2007 */
2008
check_partition_field_length()2009 bool partition_info::check_partition_field_length()
2010 {
2011 uint store_length= 0;
2012 uint i;
2013 DBUG_ENTER("partition_info::check_partition_field_length");
2014
2015 for (i= 0; i < num_part_fields; i++)
2016 store_length+= get_partition_field_store_length(part_field_array[i]);
2017 if (store_length > MAX_KEY_LENGTH)
2018 DBUG_RETURN(TRUE);
2019 store_length= 0;
2020 for (i= 0; i < num_subpart_fields; i++)
2021 store_length+= get_partition_field_store_length(subpart_field_array[i]);
2022 if (store_length > MAX_KEY_LENGTH)
2023 DBUG_RETURN(TRUE);
2024 DBUG_RETURN(FALSE);
2025 }
2026
2027
2028 /*
2029 Set up buffers and arrays for fields requiring preparation
2030 SYNOPSIS
2031 set_up_charset_field_preps()
2032
2033 RETURN VALUES
2034 TRUE Memory Allocation error
2035 FALSE Success
2036
2037 DESCRIPTION
2038 Set up arrays and buffers for fields that require special care for
2039 calculation of partition id. This is used for string fields with
2040 variable length or string fields with fixed length that isn't using
2041 the binary collation.
2042 */
2043
set_up_charset_field_preps()2044 bool partition_info::set_up_charset_field_preps()
2045 {
2046 Field *field, **ptr;
2047 uchar **char_ptrs;
2048 unsigned i;
2049 size_t size;
2050 uint tot_fields= 0;
2051 uint tot_part_fields= 0;
2052 uint tot_subpart_fields= 0;
2053 DBUG_ENTER("set_up_charset_field_preps");
2054
2055 if (!(part_type == HASH_PARTITION &&
2056 list_of_part_fields) &&
2057 check_part_func_fields(part_field_array, FALSE))
2058 {
2059 ptr= part_field_array;
2060 /* Set up arrays and buffers for those fields */
2061 while ((field= *(ptr++)))
2062 {
2063 if (field_is_partition_charset(field))
2064 {
2065 tot_part_fields++;
2066 tot_fields++;
2067 }
2068 }
2069 size= tot_part_fields * sizeof(char*);
2070 if (!(char_ptrs= (uchar**)sql_calloc(size)))
2071 goto error;
2072 part_field_buffers= char_ptrs;
2073 if (!(char_ptrs= (uchar**)sql_calloc(size)))
2074 goto error;
2075 restore_part_field_ptrs= char_ptrs;
2076 size= (tot_part_fields + 1) * sizeof(Field*);
2077 if (!(char_ptrs= (uchar**)sql_alloc(size)))
2078 goto error;
2079 part_charset_field_array= (Field**)char_ptrs;
2080 ptr= part_field_array;
2081 i= 0;
2082 while ((field= *(ptr++)))
2083 {
2084 if (field_is_partition_charset(field))
2085 {
2086 uchar *field_buf;
2087 size= field->pack_length();
2088 if (!(field_buf= (uchar*) sql_calloc(size)))
2089 goto error;
2090 part_charset_field_array[i]= field;
2091 part_field_buffers[i++]= field_buf;
2092 }
2093 }
2094 part_charset_field_array[i]= NULL;
2095 }
2096 if (is_sub_partitioned() && !list_of_subpart_fields &&
2097 check_part_func_fields(subpart_field_array, FALSE))
2098 {
2099 /* Set up arrays and buffers for those fields */
2100 ptr= subpart_field_array;
2101 while ((field= *(ptr++)))
2102 {
2103 if (field_is_partition_charset(field))
2104 {
2105 tot_subpart_fields++;
2106 tot_fields++;
2107 }
2108 }
2109 size= tot_subpart_fields * sizeof(char*);
2110 if (!(char_ptrs= (uchar**) sql_calloc(size)))
2111 goto error;
2112 subpart_field_buffers= char_ptrs;
2113 if (!(char_ptrs= (uchar**) sql_calloc(size)))
2114 goto error;
2115 restore_subpart_field_ptrs= char_ptrs;
2116 size= (tot_subpart_fields + 1) * sizeof(Field*);
2117 if (!(char_ptrs= (uchar**) sql_alloc(size)))
2118 goto error;
2119 subpart_charset_field_array= (Field**)char_ptrs;
2120 ptr= subpart_field_array;
2121 i= 0;
2122 while ((field= *(ptr++)))
2123 {
2124 uchar *field_buf= NULL;
2125
2126 if (!field_is_partition_charset(field))
2127 continue;
2128 size= field->pack_length();
2129 if (!(field_buf= (uchar*) sql_calloc(size)))
2130 goto error;
2131 subpart_charset_field_array[i]= field;
2132 subpart_field_buffers[i++]= field_buf;
2133 }
2134 subpart_charset_field_array[i]= NULL;
2135 }
2136 DBUG_RETURN(FALSE);
2137 error:
2138 mem_alloc_error(size);
2139 DBUG_RETURN(TRUE);
2140 }
2141
2142
2143 /*
2144 Check if path does not contain mysql data home directory
2145 for partition elements with data directory and index directory
2146
2147 SYNOPSIS
2148 check_partition_dirs()
2149 part_info partition_info struct
2150
2151 RETURN VALUES
2152 0 ok
2153 1 error
2154 */
2155
check_partition_dirs(partition_info * part_info)2156 bool check_partition_dirs(partition_info *part_info)
2157 {
2158 if (!part_info)
2159 return 0;
2160
2161 partition_element *part_elem;
2162 List_iterator<partition_element> part_it(part_info->partitions);
2163 while ((part_elem= part_it++))
2164 {
2165 if (part_elem->subpartitions.elements)
2166 {
2167 List_iterator<partition_element> sub_it(part_elem->subpartitions);
2168 partition_element *subpart_elem;
2169 while ((subpart_elem= sub_it++))
2170 {
2171 if (test_if_data_home_dir(subpart_elem->data_file_name))
2172 goto dd_err;
2173 if (test_if_data_home_dir(subpart_elem->index_file_name))
2174 goto id_err;
2175 }
2176 }
2177 else
2178 {
2179 if (test_if_data_home_dir(part_elem->data_file_name))
2180 goto dd_err;
2181 if (test_if_data_home_dir(part_elem->index_file_name))
2182 goto id_err;
2183 }
2184 }
2185 return 0;
2186
2187 dd_err:
2188 my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECTORY");
2189 return 1;
2190
2191 id_err:
2192 my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECTORY");
2193 return 1;
2194 }
2195
2196
2197 /**
2198 Check what kind of error to report.
2199
2200 @param use_subpart_expr Use the subpart_expr instead of part_expr
2201 */
2202
report_part_expr_error(bool use_subpart_expr)2203 void partition_info::report_part_expr_error(bool use_subpart_expr)
2204 {
2205 Item *expr= part_expr;
2206 DBUG_ENTER("partition_info::report_part_expr_error");
2207 if (use_subpart_expr)
2208 expr= subpart_expr;
2209
2210 if (expr->type() == Item::FIELD_ITEM)
2211 {
2212 partition_type type= part_type;
2213 bool list_of_fields= list_of_part_fields;
2214 Item_field *item_field= (Item_field*) expr;
2215 /*
2216 The expression consists of a single field.
2217 It must be of integer type unless KEY or COLUMNS partitioning.
2218 */
2219 if (use_subpart_expr)
2220 {
2221 type= subpart_type;
2222 list_of_fields= list_of_subpart_fields;
2223 }
2224 if (!column_list &&
2225 item_field->field &&
2226 item_field->field->result_type() != INT_RESULT &&
2227 !(type == HASH_PARTITION && list_of_fields))
2228 {
2229 my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
2230 item_field->item_name.ptr());
2231 DBUG_VOID_RETURN;
2232 }
2233 }
2234 if (use_subpart_expr)
2235 my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), "SUBPARTITION");
2236 else
2237 my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), "PARTITION");
2238 DBUG_VOID_RETURN;
2239 }
2240
2241
2242 /**
2243 Check if fields are in the partitioning expression.
2244
2245 @param fields List of Items (fields)
2246
2247 @return True if any field in the fields list is used by a partitioning expr.
2248 @retval true At least one field in the field list is found.
2249 @retval false No field is within any partitioning expression.
2250 */
2251
is_fields_in_part_expr(List<Item> & fields)2252 bool partition_info::is_fields_in_part_expr(List<Item> &fields)
2253 {
2254 List_iterator<Item> it(fields);
2255 Item *item;
2256 Item_field *field;
2257 DBUG_ENTER("is_fields_in_part_expr");
2258 while ((item= it++))
2259 {
2260 field= item->field_for_view_update();
2261 assert(field->field->table == table);
2262 if (bitmap_is_set(&full_part_field_set, field->field->field_index))
2263 DBUG_RETURN(true);
2264 }
2265 DBUG_RETURN(false);
2266 }
2267
2268
2269 /**
2270 Check if all partitioning fields are included.
2271 */
2272
is_full_part_expr_in_fields(List<Item> & fields)2273 bool partition_info::is_full_part_expr_in_fields(List<Item> &fields)
2274 {
2275 Field **part_field= full_part_field_array;
2276 assert(*part_field);
2277 DBUG_ENTER("is_full_part_expr_in_fields");
2278 /*
2279 It is very seldom many fields in full_part_field_array, so it is OK
2280 to loop over all of them instead of creating a bitmap fields argument
2281 to compare with.
2282 */
2283 do
2284 {
2285 List_iterator<Item> it(fields);
2286 Item *item;
2287 Item_field *field;
2288 bool found= false;
2289
2290 while ((item= it++))
2291 {
2292 field= item->field_for_view_update();
2293 assert(field->field->table == table);
2294 if (*part_field == field->field)
2295 {
2296 found= true;
2297 break;
2298 }
2299 }
2300 if (!found)
2301 DBUG_RETURN(false);
2302 } while (*(++part_field));
2303 DBUG_RETURN(true);
2304 }
2305
2306
2307 /**
2308 Create a new column value in current list with maxvalue.
2309
2310 @return Operation status
2311 @retval TRUE Error
2312 @retval FALSE Success
2313
2314 @note Called from parser.
2315 */
2316
add_max_value()2317 bool partition_info::add_max_value()
2318 {
2319 DBUG_ENTER("partition_info::add_max_value");
2320
2321 part_column_list_val *col_val;
2322 if (!(col_val= add_column_value()))
2323 {
2324 DBUG_RETURN(TRUE);
2325 }
2326 col_val->max_value= TRUE;
2327 DBUG_RETURN(FALSE);
2328 }
2329
2330
2331 /**
2332 Create a new column value in current list.
2333
2334 @return Pointer to a new part_column_list_val
2335 @retval != 0 A part_column_list_val object which have been
2336 inserted into its list
2337 @retval NULL Memory allocation failure
2338
2339 @note Called from parser.
2340 */
2341
add_column_value()2342 part_column_list_val *partition_info::add_column_value()
2343 {
2344 uint max_val= num_columns ? num_columns : MAX_REF_PARTS;
2345 DBUG_ENTER("add_column_value");
2346 DBUG_PRINT("enter", ("num_columns = %u, curr_list_object %u, max_val = %u",
2347 num_columns, curr_list_object, max_val));
2348 if (curr_list_object < max_val)
2349 {
2350 curr_list_val->added_items++;
2351 DBUG_RETURN(&curr_list_val->col_val_array[curr_list_object++]);
2352 }
2353 if (!num_columns && part_type == LIST_PARTITION)
2354 {
2355 /*
2356 We're trying to add more than MAX_REF_PARTS, this can happen
2357 in ALTER TABLE using List partitions where the first partition
2358 uses VALUES IN (1,2,3...,17) where the number of fields in
2359 the list is more than MAX_REF_PARTS, in this case we know
2360 that the number of columns must be 1 and we thus reorganize
2361 into the structure used for 1 column. After this we call
2362 ourselves recursively which should always succeed.
2363 */
2364 if (!reorganize_into_single_field_col_val() && !init_column_part())
2365 {
2366 DBUG_RETURN(add_column_value());
2367 }
2368 DBUG_RETURN(NULL);
2369 }
2370 if (column_list)
2371 {
2372 my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
2373 }
2374 else
2375 {
2376 if (part_type == RANGE_PARTITION)
2377 my_error(ER_TOO_MANY_VALUES_ERROR, MYF(0), "RANGE");
2378 else
2379 my_error(ER_TOO_MANY_VALUES_ERROR, MYF(0), "LIST");
2380 }
2381 DBUG_RETURN(NULL);
2382 }
2383
2384
2385 /**
2386 Initialise part_elem_value object at setting of a new object.
2387
2388 @param col_val Column value object to be initialised
2389 @param item Item object representing column value
2390
2391 @return Operation status
2392 @retval TRUE Failure
2393 @retval FALSE Success
2394
2395 @note Helper functions to functions called by parser.
2396 */
2397
init_col_val(part_column_list_val * col_val,Item * item)2398 void partition_info::init_col_val(part_column_list_val *col_val, Item *item)
2399 {
2400 DBUG_ENTER("partition_info::init_col_val");
2401
2402 col_val->item_expression= item;
2403 col_val->null_value= item->null_value;
2404 if (item->result_type() == INT_RESULT)
2405 {
2406 /*
2407 This could be both column_list partitioning and function
2408 partitioning, but it doesn't hurt to set the function
2409 partitioning flags about unsignedness.
2410 */
2411 curr_list_val->value= item->val_int();
2412 curr_list_val->unsigned_flag= TRUE;
2413 if (!item->unsigned_flag &&
2414 curr_list_val->value < 0)
2415 curr_list_val->unsigned_flag= FALSE;
2416 if (!curr_list_val->unsigned_flag)
2417 curr_part_elem->signed_flag= TRUE;
2418 }
2419 col_val->part_info= NULL;
2420 DBUG_VOID_RETURN;
2421 }
2422
2423
2424 /**
2425 Add a column value in VALUES LESS THAN or VALUES IN.
2426
2427 @param thd Thread object
2428 @param item Item object representing column value
2429
2430 @return Operation status
2431 @retval TRUE Failure
2432 @retval FALSE Success
2433
2434 @note Called from parser.
2435 */
2436
add_column_list_value(THD * thd,Item * item)2437 bool partition_info::add_column_list_value(THD *thd, Item *item)
2438 {
2439 part_column_list_val *col_val;
2440 Name_resolution_context *context= &thd->lex->current_select()->context;
2441 TABLE_LIST *save_list= context->table_list;
2442 const char *save_where= thd->where;
2443 DBUG_ENTER("partition_info::add_column_list_value");
2444
2445 if (part_type == LIST_PARTITION &&
2446 num_columns == 1U)
2447 {
2448 if (init_column_part())
2449 {
2450 DBUG_RETURN(TRUE);
2451 }
2452 }
2453
2454 context->table_list= 0;
2455 if (column_list)
2456 thd->where= "field list";
2457 else
2458 thd->where= "partition function";
2459
2460 if (item->walk(&Item::check_partition_func_processor, Item::WALK_POSTFIX,
2461 NULL))
2462 {
2463 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2464 DBUG_RETURN(TRUE);
2465 }
2466 if (item->fix_fields(thd, (Item**)0) ||
2467 ((context->table_list= save_list), FALSE) ||
2468 (!item->const_item()))
2469 {
2470 context->table_list= save_list;
2471 thd->where= save_where;
2472 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2473 DBUG_RETURN(TRUE);
2474 }
2475 thd->where= save_where;
2476
2477 if (!(col_val= add_column_value()))
2478 {
2479 DBUG_RETURN(TRUE);
2480 }
2481 init_col_val(col_val, item);
2482 DBUG_RETURN(FALSE);
2483 }
2484
2485
2486 /**
2487 Initialize a new column for VALUES {LESS THAN|IN}.
2488
2489 Initialize part_info object for receiving a set of column values
2490 for a partition, called when parser reaches VALUES LESS THAN or
2491 VALUES IN.
2492
2493 @return Operation status
2494 @retval TRUE Failure
2495 @retval FALSE Success
2496 */
2497
init_column_part()2498 bool partition_info::init_column_part()
2499 {
2500 partition_element *p_elem= curr_part_elem;
2501 part_column_list_val *col_val_array;
2502 part_elem_value *list_val;
2503 uint loc_num_columns;
2504 DBUG_ENTER("partition_info::init_column_part");
2505
2506 if (!(list_val=
2507 (part_elem_value*)sql_calloc(sizeof(part_elem_value))) ||
2508 p_elem->list_val_list.push_back(list_val))
2509 {
2510 mem_alloc_error(sizeof(part_elem_value));
2511 DBUG_RETURN(TRUE);
2512 }
2513 if (num_columns)
2514 loc_num_columns= num_columns;
2515 else
2516 loc_num_columns= MAX_REF_PARTS;
2517 if (!(col_val_array=
2518 (part_column_list_val*)sql_calloc(loc_num_columns *
2519 sizeof(part_column_list_val))))
2520 {
2521 mem_alloc_error(loc_num_columns * sizeof(part_elem_value));
2522 DBUG_RETURN(TRUE);
2523 }
2524 list_val->col_val_array= col_val_array;
2525 list_val->added_items= 0;
2526 curr_list_val= list_val;
2527 curr_list_object= 0;
2528 DBUG_RETURN(FALSE);
2529 }
2530
2531
2532 /**
2533 Reorganize the preallocated buffer into a single field col list.
2534
2535 @return Operation status
2536 @retval true Failure
2537 @retval false Success
2538
2539 @note In the case of ALTER TABLE ADD/REORGANIZE PARTITION for LIST
2540 partitions we can specify list values as:
2541 VALUES IN (v1, v2,,,, v17) if we're using the first partitioning
2542 variant with a function or a column list partitioned table with
2543 one partition field. In this case the parser knows not the
2544 number of columns start with and allocates MAX_REF_PARTS in the
2545 array. If we try to allocate something beyond MAX_REF_PARTS we
2546 will call this function to reorganize into a structure with
2547 num_columns = 1. Also when the parser knows that we used LIST
2548 partitioning and we used a VALUES IN like above where number of
2549 values was smaller than MAX_REF_PARTS or equal, then we will
2550 reorganize after discovering this in the parser.
2551 */
2552
reorganize_into_single_field_col_val()2553 bool partition_info::reorganize_into_single_field_col_val()
2554 {
2555 part_column_list_val *col_val, *new_col_val;
2556 part_elem_value *val= curr_list_val;
2557 uint num_values= num_columns;
2558 uint i;
2559 DBUG_ENTER("partition_info::reorganize_into_single_field_col_val");
2560 assert(part_type == LIST_PARTITION);
2561 assert(!num_columns || num_columns == val->added_items);
2562
2563 if (!num_values)
2564 num_values= val->added_items;
2565 num_columns= 1;
2566 val->added_items= 1U;
2567 col_val= &val->col_val_array[0];
2568 init_col_val(col_val, col_val->item_expression);
2569 for (i= 1; i < num_values; i++)
2570 {
2571 col_val= &val->col_val_array[i];
2572 if (init_column_part())
2573 {
2574 DBUG_RETURN(TRUE);
2575 }
2576 if (!(new_col_val= add_column_value()))
2577 {
2578 DBUG_RETURN(TRUE);
2579 }
2580 memcpy(new_col_val, col_val, sizeof(*col_val));
2581 init_col_val(new_col_val, col_val->item_expression);
2582 }
2583 curr_list_val= val;
2584 DBUG_RETURN(FALSE);
2585 }
2586
2587
2588 /**
2589 This function handles the case of function-based partitioning.
2590
2591 It fixes some data structures created in the parser and puts
2592 them in the format required by the rest of the partitioning
2593 code.
2594
2595 @param thd Thread object
2596 @param col_val Array of one value
2597 @param part_elem The partition instance
2598 @param part_id Id of partition instance
2599
2600 @return Operation status
2601 @retval TRUE Failure
2602 @retval FALSE Success
2603 */
2604
fix_partition_values(THD * thd,part_elem_value * val,partition_element * part_elem,uint part_id)2605 bool partition_info::fix_partition_values(THD *thd,
2606 part_elem_value *val,
2607 partition_element *part_elem,
2608 uint part_id)
2609 {
2610 part_column_list_val *col_val= val->col_val_array;
2611 DBUG_ENTER("partition_info::fix_partition_values");
2612
2613 if (col_val->fixed)
2614 {
2615 DBUG_RETURN(FALSE);
2616 }
2617 if (val->added_items != 1)
2618 {
2619 my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
2620 DBUG_RETURN(TRUE);
2621 }
2622 if (col_val->max_value)
2623 {
2624 /* The parser ensures we're not LIST partitioned here */
2625 assert(part_type == RANGE_PARTITION);
2626 if (defined_max_value)
2627 {
2628 my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
2629 DBUG_RETURN(TRUE);
2630 }
2631 if (part_id == (num_parts - 1))
2632 {
2633 defined_max_value= TRUE;
2634 part_elem->max_value= TRUE;
2635 part_elem->range_value= LLONG_MAX;
2636 }
2637 else
2638 {
2639 my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
2640 DBUG_RETURN(TRUE);
2641 }
2642 }
2643 else
2644 {
2645 Item *item_expr= col_val->item_expression;
2646 if ((val->null_value= item_expr->null_value))
2647 {
2648 if (part_elem->has_null_value)
2649 {
2650 my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
2651 DBUG_RETURN(TRUE);
2652 }
2653 part_elem->has_null_value= TRUE;
2654 }
2655 else if (item_expr->result_type() != INT_RESULT)
2656 {
2657 my_error(ER_VALUES_IS_NOT_INT_TYPE_ERROR, MYF(0),
2658 part_elem->partition_name);
2659 DBUG_RETURN(TRUE);
2660 }
2661 if (part_type == RANGE_PARTITION)
2662 {
2663 if (part_elem->has_null_value)
2664 {
2665 my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
2666 DBUG_RETURN(TRUE);
2667 }
2668 part_elem->range_value= val->value;
2669 }
2670 }
2671 col_val->fixed= 2;
2672 DBUG_RETURN(FALSE);
2673 }
2674
2675
2676 /**
2677 Get column item with a proper character set according to the field.
2678
2679 @param item Item object to start with
2680 @param field Field for which the item will be compared to
2681
2682 @return Column item
2683 @retval NULL Error
2684 @retval item Returned item
2685 */
2686
get_column_item(Item * item,Field * field)2687 Item* partition_info::get_column_item(Item *item, Field *field)
2688 {
2689 if (field->result_type() == STRING_RESULT &&
2690 item->collation.collation != field->charset())
2691 {
2692 if (!(item= convert_charset_partition_constant(item,
2693 field->charset())))
2694 {
2695 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2696 return NULL;
2697 }
2698 }
2699 return item;
2700 }
2701
2702
2703 /**
2704 Evaluate VALUES functions for column list values.
2705
2706 @param thd Thread object
2707 @param col_val List of column values
2708 @param part_id Partition id we are fixing
2709
2710 @return Operation status
2711 @retval TRUE Error
2712 @retval FALSE Success
2713
2714 @note Fix column VALUES and store in memory array adapted to the data type.
2715 */
2716
fix_column_value_functions(THD * thd,part_elem_value * val,uint part_id)2717 bool partition_info::fix_column_value_functions(THD *thd,
2718 part_elem_value *val,
2719 uint part_id)
2720 {
2721 uint n_columns= part_field_list.elements;
2722 bool result= FALSE;
2723 uint i;
2724 part_column_list_val *col_val= val->col_val_array;
2725 DBUG_ENTER("partition_info::fix_column_value_functions");
2726
2727 if (col_val->fixed > 1)
2728 {
2729 DBUG_RETURN(FALSE);
2730 }
2731 for (i= 0; i < n_columns; col_val++, i++)
2732 {
2733 Item *column_item= col_val->item_expression;
2734 Field *field= part_field_array[i];
2735 col_val->part_info= this;
2736 col_val->partition_id= part_id;
2737 if (col_val->max_value)
2738 col_val->column_value= NULL;
2739 else
2740 {
2741 col_val->column_value= NULL;
2742 if (!col_val->null_value)
2743 {
2744 uchar *val_ptr;
2745 uint len= field->pack_length();
2746 sql_mode_t save_sql_mode;
2747 bool save_got_warning;
2748
2749 if (!(column_item= get_column_item(column_item,
2750 field)))
2751 {
2752 result= TRUE;
2753 goto end;
2754 }
2755 save_sql_mode= thd->variables.sql_mode;
2756 thd->variables.sql_mode= 0;
2757 save_got_warning= thd->got_warning;
2758 thd->got_warning= 0;
2759 result= (column_item->save_in_field(field, true) ||
2760 thd->got_warning);
2761 thd->got_warning= save_got_warning;
2762 thd->variables.sql_mode= save_sql_mode;
2763 if (result)
2764 {
2765 my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
2766 goto end;
2767 }
2768 if (!(val_ptr= (uchar*) sql_calloc(len)))
2769 {
2770 mem_alloc_error(len);
2771 result= TRUE;
2772 goto end;
2773 }
2774 col_val->column_value= val_ptr;
2775 memcpy(val_ptr, field->ptr, len);
2776 }
2777 }
2778 col_val->fixed= 2;
2779 }
2780 end:
2781 DBUG_RETURN(result);
2782 }
2783
2784 /**
2785 Fix partition data from parser.
2786
2787 @details The parser generates generic data structures, we need to set them
2788 up as the rest of the code expects to find them. This is in reality part
2789 of the syntax check of the parser code.
2790
2791 It is necessary to call this function in the case of a CREATE TABLE
2792 statement, in this case we do it early in the check_partition_info
2793 function.
2794
2795 It is necessary to call this function for ALTER TABLE where we
2796 assign a completely new partition structure, in this case we do it
2797 in prep_alter_part_table after discovering that the partition
2798 structure is entirely redefined.
2799
2800 It's necessary to call this method also for ALTER TABLE ADD/REORGANIZE
2801 of partitions, in this we call it in prep_alter_part_table after
2802 making some initial checks but before going deep to check the partition
2803 info, we also assign the column_list variable before calling this function
2804 here.
2805
2806 Finally we also call it immediately after returning from parsing the
2807 partitioning text found in the frm file.
2808
2809 This function mainly fixes the VALUES parts, these are handled differently
2810 whether or not we use column list partitioning. Since the parser doesn't
2811 know which we are using we need to set-up the old data structures after
2812 the parser is complete when we know if what type of partitioning the
2813 base table is using.
2814
2815 For column lists we will handle this in the fix_column_value_function.
2816 For column lists it is sufficient to verify that the number of columns
2817 and number of elements are in synch with each other. So only partitioning
2818 using functions need to be set-up to their data structures.
2819
2820 @param thd Thread object
2821
2822 @return Operation status
2823 @retval TRUE Failure
2824 @retval FALSE Success
2825 */
2826
fix_parser_data(THD * thd)2827 bool partition_info::fix_parser_data(THD *thd)
2828 {
2829 List_iterator<partition_element> it(partitions);
2830 partition_element *part_elem;
2831 uint num_elements;
2832 uint i= 0, j, k;
2833 DBUG_ENTER("partition_info::fix_parser_data");
2834
2835 if (!(part_type == RANGE_PARTITION ||
2836 part_type == LIST_PARTITION))
2837 {
2838 if (part_type == HASH_PARTITION && list_of_part_fields)
2839 {
2840 /* KEY partitioning, check ALGORITHM = N. Should not pass the parser! */
2841 if (key_algorithm > KEY_ALGORITHM_55)
2842 {
2843 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2844 DBUG_RETURN(true);
2845 }
2846 /* If not set, use DEFAULT = 2 for CREATE and ALTER! */
2847 if ((thd_sql_command(thd) == SQLCOM_CREATE_TABLE ||
2848 thd_sql_command(thd) == SQLCOM_ALTER_TABLE) &&
2849 key_algorithm == KEY_ALGORITHM_NONE)
2850 key_algorithm= KEY_ALGORITHM_55;
2851 }
2852 DBUG_RETURN(FALSE);
2853 }
2854 if (is_sub_partitioned() && list_of_subpart_fields)
2855 {
2856 /* KEY subpartitioning, check ALGORITHM = N. Should not pass the parser! */
2857 if (key_algorithm > KEY_ALGORITHM_55)
2858 {
2859 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2860 DBUG_RETURN(true);
2861 }
2862 /* If not set, use DEFAULT = 2 for CREATE and ALTER! */
2863 if ((thd_sql_command(thd) == SQLCOM_CREATE_TABLE ||
2864 thd_sql_command(thd) == SQLCOM_ALTER_TABLE) &&
2865 key_algorithm == KEY_ALGORITHM_NONE)
2866 key_algorithm= KEY_ALGORITHM_55;
2867 }
2868 do
2869 {
2870 part_elem= it++;
2871 List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
2872 num_elements= part_elem->list_val_list.elements;
2873 assert(part_type == RANGE_PARTITION ?
2874 num_elements == 1U : TRUE);
2875 for (j= 0; j < num_elements; j++)
2876 {
2877 part_elem_value *val= list_val_it++;
2878 if (column_list)
2879 {
2880 if (val->added_items != num_columns)
2881 {
2882 my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
2883 DBUG_RETURN(TRUE);
2884 }
2885 for (k= 0; k < num_columns; k++)
2886 {
2887 part_column_list_val *col_val= &val->col_val_array[k];
2888 if (col_val->null_value && part_type == RANGE_PARTITION)
2889 {
2890 my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
2891 DBUG_RETURN(TRUE);
2892 }
2893 }
2894 }
2895 else
2896 {
2897 if (fix_partition_values(thd, val, part_elem, i))
2898 {
2899 DBUG_RETURN(TRUE);
2900 }
2901 if (val->null_value)
2902 {
2903 /*
2904 Null values aren't required in the value part, they are kept per
2905 partition instance, only LIST partitions have NULL values.
2906 */
2907 list_val_it.remove();
2908 }
2909 }
2910 }
2911 } while (++i < num_parts);
2912 DBUG_RETURN(FALSE);
2913 }
2914
2915
2916 /**
2917 helper function to compare strings that can also be
2918 a NULL pointer.
2919
2920 @param a char pointer (can be NULL).
2921 @param b char pointer (can be NULL).
2922
2923 @return false if equal
2924 @retval true strings differs
2925 @retval false strings is equal
2926 */
2927
strcmp_null(const char * a,const char * b)2928 static bool strcmp_null(const char *a, const char *b)
2929 {
2930 if (!a && !b)
2931 return false;
2932 if (a && b && !strcmp(a, b))
2933 return false;
2934 return true;
2935 }
2936
2937
2938 /**
2939 Check if the new part_info has the same partitioning.
2940
2941 @param new_part_info New partition definition to compare with.
2942
2943 @return True if not considered to have changed the partitioning.
2944 @retval true Allowed change (only .frm change, compatible distribution).
2945 @retval false Different partitioning, will need redistribution of rows.
2946
2947 @note Currently only used to allow changing from non-set key_algorithm
2948 to a specified key_algorithm, to avoid rebuild when upgrading from 5.1 of
2949 such partitioned tables using numeric columns in the partitioning expression.
2950 For more info see bug#14521864.
2951 Does not check if columns etc has changed, i.e. only for
2952 alter_info->flags == ALTER_PARTITION.
2953 */
2954
has_same_partitioning(partition_info * new_part_info)2955 bool partition_info::has_same_partitioning(partition_info *new_part_info)
2956 {
2957 DBUG_ENTER("partition_info::has_same_partitioning");
2958
2959 assert(part_field_array && part_field_array[0]);
2960
2961 /*
2962 Only consider pre 5.5.3 .frm's to have same partitioning as
2963 a new one with KEY ALGORITHM = 1 ().
2964 */
2965
2966 if (part_field_array[0]->table->s->mysql_version >= 50503)
2967 DBUG_RETURN(false);
2968
2969 if (!new_part_info ||
2970 part_type != new_part_info->part_type ||
2971 num_parts != new_part_info->num_parts ||
2972 use_default_partitions != new_part_info->use_default_partitions ||
2973 new_part_info->is_sub_partitioned() != is_sub_partitioned())
2974 DBUG_RETURN(false);
2975
2976 if (part_type != HASH_PARTITION)
2977 {
2978 /*
2979 RANGE or LIST partitioning, check if KEY subpartitioned.
2980 Also COLUMNS partitioning was added in 5.5, so treat that as different.
2981 */
2982 if (!is_sub_partitioned() ||
2983 !new_part_info->is_sub_partitioned() ||
2984 column_list ||
2985 new_part_info->column_list ||
2986 !list_of_subpart_fields ||
2987 !new_part_info->list_of_subpart_fields ||
2988 new_part_info->num_subparts != num_subparts ||
2989 new_part_info->subpart_field_list.elements !=
2990 subpart_field_list.elements ||
2991 new_part_info->use_default_subpartitions !=
2992 use_default_subpartitions)
2993 DBUG_RETURN(false);
2994 }
2995 else
2996 {
2997 /* Check if KEY partitioned. */
2998 if (!new_part_info->list_of_part_fields ||
2999 !list_of_part_fields ||
3000 new_part_info->part_field_list.elements != part_field_list.elements)
3001 DBUG_RETURN(false);
3002 }
3003
3004 /* Check that it will use the same fields in KEY (fields) list. */
3005 List_iterator<char> old_field_name_it(part_field_list);
3006 List_iterator<char> new_field_name_it(new_part_info->part_field_list);
3007 char *old_name, *new_name;
3008 while ((old_name= old_field_name_it++))
3009 {
3010 new_name= new_field_name_it++;
3011 if (!new_name || my_strcasecmp(system_charset_info,
3012 new_name,
3013 old_name))
3014 DBUG_RETURN(false);
3015 }
3016
3017 if (is_sub_partitioned())
3018 {
3019 /* Check that it will use the same fields in KEY subpart fields list. */
3020 List_iterator<char> old_field_name_it(subpart_field_list);
3021 List_iterator<char> new_field_name_it(new_part_info->subpart_field_list);
3022 char *old_name, *new_name;
3023 while ((old_name= old_field_name_it++))
3024 {
3025 new_name= new_field_name_it++;
3026 if (!new_name || my_strcasecmp(system_charset_info,
3027 new_name,
3028 old_name))
3029 DBUG_RETURN(false);
3030 }
3031 }
3032
3033 if (!use_default_partitions)
3034 {
3035 /*
3036 Loop over partitions/subpartition to verify that they are
3037 the same, including state and name.
3038 */
3039 List_iterator<partition_element> part_it(partitions);
3040 List_iterator<partition_element> new_part_it(new_part_info->partitions);
3041 uint i= 0;
3042 do
3043 {
3044 partition_element *part_elem= part_it++;
3045 partition_element *new_part_elem= new_part_it++;
3046 /*
3047 The following must match:
3048 partition_name, tablespace_name, data_file_name, index_file_name,
3049 engine_type, part_max_rows, part_min_rows, nodegroup_id.
3050 (max_value, signed_flag, has_null_value only on partition level,
3051 RANGE/LIST)
3052 The following can differ:
3053 - part_comment
3054 part_state must be PART_NORMAL!
3055 */
3056 if (!part_elem || !new_part_elem ||
3057 strcmp(part_elem->partition_name,
3058 new_part_elem->partition_name) ||
3059 part_elem->part_state != PART_NORMAL ||
3060 new_part_elem->part_state != PART_NORMAL ||
3061 part_elem->max_value != new_part_elem->max_value ||
3062 part_elem->signed_flag != new_part_elem->signed_flag ||
3063 part_elem->has_null_value != new_part_elem->has_null_value)
3064 DBUG_RETURN(false);
3065
3066 /* new_part_elem may not have engine_type set! */
3067 if (new_part_elem->engine_type &&
3068 part_elem->engine_type != new_part_elem->engine_type)
3069 DBUG_RETURN(false);
3070
3071 if (is_sub_partitioned())
3072 {
3073 /*
3074 Check that both old and new partition has the same definition
3075 (VALUES IN/VALUES LESS THAN) (No COLUMNS partitioning, see above)
3076 */
3077 if (part_type == LIST_PARTITION)
3078 {
3079 List_iterator<part_elem_value> list_vals(part_elem->list_val_list);
3080 List_iterator<part_elem_value>
3081 new_list_vals(new_part_elem->list_val_list);
3082 part_elem_value *val;
3083 part_elem_value *new_val;
3084 while ((val= list_vals++))
3085 {
3086 new_val= new_list_vals++;
3087 if (!new_val)
3088 DBUG_RETURN(false);
3089 if ((!val->null_value && !new_val->null_value) &&
3090 val->value != new_val->value)
3091 DBUG_RETURN(false);
3092 }
3093 if (new_list_vals++)
3094 DBUG_RETURN(false);
3095 }
3096 else
3097 {
3098 assert(part_type == RANGE_PARTITION);
3099 if (new_part_elem->range_value != part_elem->range_value)
3100 DBUG_RETURN(false);
3101 }
3102
3103 if (!use_default_subpartitions)
3104 {
3105 List_iterator<partition_element>
3106 sub_part_it(part_elem->subpartitions);
3107 List_iterator<partition_element>
3108 new_sub_part_it(new_part_elem->subpartitions);
3109 uint j= 0;
3110 do
3111 {
3112 partition_element *sub_part_elem= sub_part_it++;
3113 partition_element *new_sub_part_elem= new_sub_part_it++;
3114 /* new_part_elem may not have engine_type set! */
3115 if (new_sub_part_elem->engine_type &&
3116 sub_part_elem->engine_type != new_sub_part_elem->engine_type)
3117 DBUG_RETURN(false);
3118
3119 if (strcmp(sub_part_elem->partition_name,
3120 new_sub_part_elem->partition_name) ||
3121 sub_part_elem->part_state != PART_NORMAL ||
3122 new_sub_part_elem->part_state != PART_NORMAL ||
3123 sub_part_elem->part_min_rows !=
3124 new_sub_part_elem->part_min_rows ||
3125 sub_part_elem->part_max_rows !=
3126 new_sub_part_elem->part_max_rows ||
3127 sub_part_elem->nodegroup_id !=
3128 new_sub_part_elem->nodegroup_id)
3129 DBUG_RETURN(false);
3130
3131 if (strcmp_null(sub_part_elem->data_file_name,
3132 new_sub_part_elem->data_file_name) ||
3133 strcmp_null(sub_part_elem->index_file_name,
3134 new_sub_part_elem->index_file_name) ||
3135 strcmp_null(sub_part_elem->tablespace_name,
3136 new_sub_part_elem->tablespace_name))
3137 DBUG_RETURN(false);
3138
3139 } while (++j < num_subparts);
3140 }
3141 }
3142 else
3143 {
3144 if (part_elem->part_min_rows != new_part_elem->part_min_rows ||
3145 part_elem->part_max_rows != new_part_elem->part_max_rows ||
3146 part_elem->nodegroup_id != new_part_elem->nodegroup_id)
3147 DBUG_RETURN(false);
3148
3149 if (strcmp_null(part_elem->data_file_name,
3150 new_part_elem->data_file_name) ||
3151 strcmp_null(part_elem->index_file_name,
3152 new_part_elem->index_file_name) ||
3153 strcmp_null(part_elem->tablespace_name,
3154 new_part_elem->tablespace_name))
3155 DBUG_RETURN(false);
3156 }
3157 } while (++i < num_parts);
3158 }
3159
3160 /*
3161 Only if key_algorithm was not specified before and it is now set,
3162 consider this as nothing was changed, and allow change without rebuild!
3163 */
3164 if (key_algorithm != partition_info::KEY_ALGORITHM_NONE ||
3165 new_part_info->key_algorithm == partition_info::KEY_ALGORITHM_NONE)
3166 DBUG_RETURN(false);
3167
3168 DBUG_RETURN(true);
3169 }
3170
has_same_column_order(List<Create_field> * create_list,Field ** field_array)3171 static bool has_same_column_order(List<Create_field> *create_list,
3172 Field** field_array)
3173 {
3174 Field **f_ptr;
3175 List_iterator_fast<Create_field> new_field_it;
3176 Create_field *new_field= NULL;
3177 new_field_it.init(*create_list);
3178
3179 for (f_ptr= field_array; *f_ptr; f_ptr++)
3180 {
3181 while ((new_field= new_field_it++))
3182 {
3183 if (new_field->field == *f_ptr)
3184 break;
3185 }
3186 if (!new_field)
3187 break;
3188 }
3189
3190 if (!new_field)
3191 {
3192 /* Not same order!*/
3193 return false;
3194 }
3195 return true;
3196 }
3197
3198
3199 /**
3200 Check if the partitioning columns are in the same order as the given list.
3201
3202 Used to see if INPLACE alter can be allowed or not. If the order is
3203 different then the rows must be redistributed for KEY [sub]partitioning.
3204
3205 @param[in] create_list Column list after ALTER TABLE.
3206 @return true is same order as before ALTER TABLE, else false.
3207 */
same_key_column_order(List<Create_field> * create_list)3208 bool partition_info::same_key_column_order(List<Create_field> *create_list)
3209 {
3210 /* Only need to check for KEY [sub] partitioning. */
3211 if (list_of_part_fields && !column_list)
3212 {
3213 if (!has_same_column_order(create_list, part_field_array))
3214 return false;
3215 }
3216 if (list_of_subpart_fields)
3217 {
3218 if (!has_same_column_order(create_list, subpart_field_array))
3219 return false;
3220 }
3221 return true;
3222 }
3223
3224
print_debug(const char * str,uint * value)3225 void partition_info::print_debug(const char *str, uint *value)
3226 {
3227 DBUG_ENTER("print_debug");
3228 if (value)
3229 DBUG_PRINT("info", ("parser: %s, val = %u", str, *value));
3230 else
3231 DBUG_PRINT("info", ("parser: %s", str));
3232 DBUG_VOID_RETURN;
3233 }
3234
has_external_data_or_index_dir(partition_info & pi)3235 bool has_external_data_or_index_dir(partition_info &pi)
3236 {
3237 List_iterator<partition_element> part_it(pi.partitions);
3238 for (partition_element *part= part_it++; part; part= part_it++)
3239 {
3240 if (part->data_file_name != NULL || part->index_file_name != NULL)
3241 {
3242 return true;
3243 }
3244 List_iterator<partition_element> subpart_it(part->subpartitions);
3245 for (const partition_element *subpart= subpart_it++;
3246 subpart;
3247 subpart= subpart_it++)
3248 {
3249 if (subpart->data_file_name != NULL || subpart->index_file_name != NULL)
3250 {
3251 return true;
3252 }
3253 }
3254 }
3255 return false;
3256 }
3257
3258
3259 /**
3260 Fill the Tablespace_hash_set with the tablespace names
3261 used by the partitions on the table.
3262
3263 @param part_info - Partition info that could be using tablespaces.
3264 @param tablespace_set - (OUT) Tablespace_hash_set where tablespace
3265 names are collected.
3266
3267 @return true - On failure.
3268 @return false - On success.
3269 */
fill_partition_tablespace_names(partition_info * part_info,Tablespace_hash_set * tablespace_set)3270 bool fill_partition_tablespace_names(
3271 partition_info *part_info,
3272 Tablespace_hash_set *tablespace_set)
3273 {
3274 // Do nothing if table is not partitioned.
3275 if (!part_info)
3276 return false;
3277
3278 // Traverse through all partitions.
3279 List_iterator<partition_element> part_it(part_info->partitions);
3280 partition_element *part_elem;
3281 while ((part_elem= part_it++))
3282 {
3283 // Add tablespace name from partition elements, if used.
3284 if (part_elem->tablespace_name &&
3285 strlen(part_elem->tablespace_name) &&
3286 tablespace_set->insert(const_cast<char*>(part_elem->tablespace_name)))
3287 return true;
3288
3289 // Traverse through all subpartitions.
3290 List_iterator<partition_element> sub_it(part_elem->subpartitions);
3291 partition_element *sub_elem;
3292 while ((sub_elem= sub_it++))
3293 {
3294 // Add tablespace name from sub-partition elements, if used.
3295 if (sub_elem->tablespace_name &&
3296 strlen(sub_elem->tablespace_name) &&
3297 tablespace_set->insert(const_cast<char*>(sub_elem->tablespace_name)))
3298 return true;
3299
3300 }
3301 }
3302
3303 return false;
3304 }
3305
3306 /**
3307 Check if all tablespace names specified for partitions
3308 are valid.
3309
3310 @param part_info - Partition info that could be using tablespaces.
3311
3312 @return true - One of tablespace names specified is invalid and
3313 a error is reported.
3314 @return false - All the tablespace names specified for
3315 partitions are valid.
3316 */
check_partition_tablespace_names(partition_info * part_info)3317 bool check_partition_tablespace_names(partition_info *part_info)
3318 {
3319 // Do nothing if table is not partitioned.
3320 if (!part_info)
3321 return false;
3322
3323 // Traverse through all partitions.
3324 List_iterator<partition_element> part_it(part_info->partitions);
3325 partition_element *part_elem;
3326 while ((part_elem= part_it++))
3327 {
3328 // Check tablespace names from partition elements, if used.
3329 if (part_elem->tablespace_name &&
3330 check_tablespace_name(part_elem->tablespace_name))
3331 return true;
3332
3333 // Traverse through all subpartitions.
3334 List_iterator<partition_element> sub_it(part_elem->subpartitions);
3335 partition_element *sub_elem;
3336 while ((sub_elem= sub_it++))
3337 {
3338 // Add tablespace name from sub-partition elements, if used.
3339 if (sub_elem->tablespace_name &&
3340 check_tablespace_name(sub_elem->tablespace_name))
3341 return true;
3342 }
3343 }
3344
3345 return false;
3346 }
3347
3348