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