1/* Copyright (c) 2006, 2015, Oracle and/or its affiliates.
2 Copyright (c) 2010, 2018, MariaDB Corporation.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17/* Some general useful functions */
18
19#ifdef USE_PRAGMA_IMPLEMENTATION
20#pragma implementation
21#endif
22
23#include "mariadb.h"
24#include <my_global.h>
25#include <tztime.h>
26#include "sql_priv.h"
27// Required to get server definitions for mysql/plugin.h right
28#include "sql_plugin.h"
29#include "sql_partition.h" // partition_info.h: LIST_PART_ENTRY
30 // NOT_A_PARTITION_ID
31#include "partition_info.h"
32#include "sql_parse.h"
33#include "sql_acl.h" // *_ACL
34#include "sql_base.h" // fill_record
35#include "sql_statistics.h" // vers_stat_end
36#include "vers_utils.h"
37#include "lock.h"
38
39#ifdef WITH_PARTITION_STORAGE_ENGINE
40#include "ha_partition.h"
41
42
43partition_info *partition_info::get_clone(THD *thd)
44{
45 MEM_ROOT *mem_root= thd->mem_root;
46 DBUG_ENTER("partition_info::get_clone");
47
48 List_iterator<partition_element> part_it(partitions);
49 partition_element *part;
50 partition_info *clone= new (mem_root) partition_info(*this);
51 if (unlikely(!clone))
52 DBUG_RETURN(NULL);
53
54 memset(&(clone->read_partitions), 0, sizeof(clone->read_partitions));
55 memset(&(clone->lock_partitions), 0, sizeof(clone->lock_partitions));
56 clone->bitmaps_are_initialized= FALSE;
57 clone->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 (mem_root) partition_element();
64 if (!part_clone)
65 DBUG_RETURN(NULL);
66
67 memcpy(part_clone, part, sizeof(partition_element));
68 part_clone->subpartitions.empty();
69 while ((subpart= (subpart_it++)))
70 {
71 partition_element *subpart_clone= new (mem_root) partition_element();
72 if (!subpart_clone)
73 DBUG_RETURN(NULL);
74
75 memcpy(subpart_clone, subpart, sizeof(partition_element));
76 part_clone->subpartitions.push_back(subpart_clone, mem_root);
77 }
78 clone->partitions.push_back(part_clone, mem_root);
79 part_clone->list_val_list.empty();
80 List_iterator<part_elem_value> list_val_it(part->list_val_list);
81 part_elem_value *new_val_arr=
82 (part_elem_value *)alloc_root(mem_root, sizeof(part_elem_value) *
83 part->list_val_list.elements);
84 if (!new_val_arr)
85 DBUG_RETURN(NULL);
86
87 p_column_list_val *new_colval_arr=
88 (p_column_list_val*)alloc_root(mem_root, sizeof(p_column_list_val) *
89 num_columns *
90 part->list_val_list.elements);
91 if (!new_colval_arr)
92 DBUG_RETURN(NULL);
93
94 part_elem_value *val;
95 while ((val= list_val_it++))
96 {
97 part_elem_value *new_val= new_val_arr++;
98 memcpy(new_val, val, sizeof(part_elem_value));
99 if (!val->null_value)
100 {
101 p_column_list_val *new_colval= new_colval_arr;
102 new_colval_arr+= num_columns;
103 memcpy(new_colval, val->col_val_array,
104 sizeof(p_column_list_val) * num_columns);
105 new_val->col_val_array= new_colval;
106 }
107 part_clone->list_val_list.push_back(new_val, mem_root);
108 }
109 }
110 if (part_type == VERSIONING_PARTITION && vers_info)
111 {
112 // clone Vers_part_info; set now_part, hist_part
113 clone->vers_info= new (mem_root) Vers_part_info(*vers_info);
114 List_iterator<partition_element> it(clone->partitions);
115 while ((part= it++))
116 {
117 if (vers_info->now_part && part->id == vers_info->now_part->id)
118 clone->vers_info->now_part= part;
119 else if (vers_info->hist_part && part->id == vers_info->hist_part->id)
120 clone->vers_info->hist_part= part;
121 } // while ((part= it++))
122 } // if (part_type == VERSIONING_PARTITION ...
123 DBUG_RETURN(clone);
124}
125
126/**
127 Mark named [sub]partition to be used/locked.
128
129 @param part_name Partition name to match.
130 @param length Partition name length.
131
132 @return Success if partition found
133 @retval true Partition found
134 @retval false Partition not found
135*/
136
137bool partition_info::add_named_partition(const char *part_name, size_t length)
138{
139 HASH *part_name_hash;
140 PART_NAME_DEF *part_def;
141 Partition_share *part_share;
142 DBUG_ENTER("partition_info::add_named_partition");
143 DBUG_ASSERT(table && table->s && table->s->ha_share);
144 part_share= static_cast<Partition_share*>((table->s->ha_share));
145 DBUG_ASSERT(part_share->partition_name_hash_initialized);
146 part_name_hash= &part_share->partition_name_hash;
147 DBUG_ASSERT(part_name_hash->records);
148
149 part_def= (PART_NAME_DEF*) my_hash_search(part_name_hash,
150 (const uchar*) part_name,
151 length);
152 if (!part_def)
153 {
154 my_error(ER_UNKNOWN_PARTITION, MYF(0), part_name, table->alias.c_ptr());
155 DBUG_RETURN(true);
156 }
157
158 if (part_def->is_subpart)
159 {
160 bitmap_set_bit(&read_partitions, part_def->part_id);
161 }
162 else
163 {
164 if (is_sub_partitioned())
165 {
166 /* Mark all subpartitions in the partition */
167 uint j, start= part_def->part_id;
168 uint end= start + num_subparts;
169 for (j= start; j < end; j++)
170 bitmap_set_bit(&read_partitions, j);
171 }
172 else
173 bitmap_set_bit(&read_partitions, part_def->part_id);
174 }
175 DBUG_PRINT("info", ("Found partition %u is_subpart %d for name %s",
176 part_def->part_id, part_def->is_subpart,
177 part_name));
178 DBUG_RETURN(false);
179}
180
181
182/**
183 Mark named [sub]partition to be used/locked.
184
185 @param part_elem Partition element that matched.
186*/
187
188bool partition_info::set_named_partition_bitmap(const char *part_name, size_t length)
189{
190 DBUG_ENTER("partition_info::set_named_partition_bitmap");
191 bitmap_clear_all(&read_partitions);
192 if (add_named_partition(part_name, length))
193 DBUG_RETURN(true);
194 bitmap_copy(&lock_partitions, &read_partitions);
195 DBUG_RETURN(false);
196}
197
198
199
200/**
201 Prune away partitions not mentioned in the PARTITION () clause,
202 if used.
203
204 @param table_list Table list pointing to table to prune.
205
206 @return Operation status
207 @retval false Success
208 @retval true Failure
209*/
210bool partition_info::set_read_partitions(List<char> *partition_names)
211{
212 DBUG_ENTER("partition_info::set_read_partitions");
213 if (!partition_names || !partition_names->elements)
214 {
215 DBUG_RETURN(true);
216 }
217
218 uint num_names= partition_names->elements;
219 List_iterator<char> partition_names_it(*partition_names);
220 uint i= 0;
221 /*
222 TODO: When adding support for FK in partitioned tables, the referenced
223 table must probably lock all partitions for read, and also write depending
224 of ON DELETE/UPDATE.
225 */
226 bitmap_clear_all(&read_partitions);
227
228 /* No check for duplicate names or overlapping partitions/subpartitions. */
229
230 DBUG_PRINT("info", ("Searching through partition_name_hash"));
231 do
232 {
233 char *part_name= partition_names_it++;
234 if (add_named_partition(part_name, strlen(part_name)))
235 DBUG_RETURN(true);
236 } while (++i < num_names);
237 DBUG_RETURN(false);
238}
239
240
241
242/**
243 Prune away partitions not mentioned in the PARTITION () clause,
244 if used.
245
246 @param partition_names list of names of partitions.
247
248 @return Operation status
249 @retval true Failure
250 @retval false Success
251*/
252bool partition_info::prune_partition_bitmaps(List<String> *partition_names)
253{
254 List_iterator<String> partition_names_it(*(partition_names));
255 uint num_names= partition_names->elements;
256 uint i= 0;
257 DBUG_ENTER("partition_info::prune_partition_bitmaps");
258
259 if (num_names < 1)
260 DBUG_RETURN(true);
261
262 /*
263 TODO: When adding support for FK in partitioned tables, the referenced
264 table must probably lock all partitions for read, and also write depending
265 of ON DELETE/UPDATE.
266 */
267 bitmap_clear_all(&read_partitions);
268
269 /* No check for duplicate names or overlapping partitions/subpartitions. */
270
271 DBUG_PRINT("info", ("Searching through partition_name_hash"));
272 do
273 {
274 String *part_name_str= partition_names_it++;
275 if (add_named_partition(part_name_str->c_ptr(), part_name_str->length()))
276 DBUG_RETURN(true);
277 } while (++i < num_names);
278 DBUG_RETURN(false);
279}
280
281
282/**
283 Set read/lock_partitions bitmap over non pruned partitions
284
285 @param partition_names list of partition names to query
286
287 @return Operation status
288 @retval FALSE OK
289 @retval TRUE Failed to allocate memory for bitmap or list of partitions
290 did not match
291
292 @note OK to call multiple times without the need for free_bitmaps.
293*/
294
295bool partition_info::set_partition_bitmaps(List<String> *partition_names)
296{
297 DBUG_ENTER("partition_info::set_partition_bitmaps");
298
299 DBUG_ASSERT(bitmaps_are_initialized);
300 DBUG_ASSERT(table);
301 if (!bitmaps_are_initialized)
302 DBUG_RETURN(TRUE);
303
304 if (partition_names &&
305 partition_names->elements)
306 {
307 if (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)
308 {
309 my_error(ER_PARTITION_CLAUSE_ON_NONPARTITIONED, MYF(0));
310 DBUG_RETURN(true);
311 }
312 if (prune_partition_bitmaps(partition_names))
313 DBUG_RETURN(TRUE);
314 }
315 else
316 {
317 bitmap_set_all(&read_partitions);
318 DBUG_PRINT("info", ("Set all partitions"));
319 }
320 bitmap_copy(&lock_partitions, &read_partitions);
321 DBUG_ASSERT(bitmap_get_first_set(&lock_partitions) != MY_BIT_NONE);
322 DBUG_RETURN(FALSE);
323}
324
325
326/**
327 Set read/lock_partitions bitmap over non pruned partitions
328
329 @param table_list Possible TABLE_LIST which can contain
330 list of partition names to query
331
332 @return Operation status
333 @retval FALSE OK
334 @retval TRUE Failed to allocate memory for bitmap or list of partitions
335 did not match
336
337 @note OK to call multiple times without the need for free_bitmaps.
338*/
339bool partition_info::set_partition_bitmaps_from_table(TABLE_LIST *table_list)
340{
341 List<String> *partition_names= table_list ?
342 NULL : table_list->partition_names;
343 return set_partition_bitmaps(partition_names);
344}
345
346
347/*
348 Create a memory area where default partition names are stored and fill it
349 up with the names.
350
351 SYNOPSIS
352 create_default_partition_names()
353 part_no Partition number for subparts
354 num_parts Number of partitions
355 start_no Starting partition number
356 subpart Is it subpartitions
357
358 RETURN VALUE
359 A pointer to the memory area of the default partition names
360
361 DESCRIPTION
362 A support routine for the partition code where default values are
363 generated.
364 The external routine needing this code is check_partition_info
365*/
366
367#define MAX_PART_NAME_SIZE 8
368
369char *partition_info::create_default_partition_names(THD *thd, uint part_no,
370 uint num_parts_arg,
371 uint start_no)
372{
373 char *ptr= (char*) thd->calloc(num_parts_arg * MAX_PART_NAME_SIZE);
374 char *move_ptr= ptr;
375 uint i= 0;
376 DBUG_ENTER("create_default_partition_names");
377
378 if (likely(ptr != 0))
379 {
380 do
381 {
382 sprintf(move_ptr, "p%u", (start_no + i));
383 move_ptr+= MAX_PART_NAME_SIZE;
384 } while (++i < num_parts_arg);
385 }
386 DBUG_RETURN(ptr);
387}
388
389
390/*
391 Create a unique name for the subpartition as part_name'sp''subpart_no'
392
393 SYNOPSIS
394 create_default_subpartition_name()
395 subpart_no Number of subpartition
396 part_name Name of partition
397 RETURN VALUES
398 >0 A reference to the created name string
399 0 Memory allocation error
400*/
401
402char *partition_info::create_default_subpartition_name(THD *thd, uint subpart_no,
403 const char *part_name)
404{
405 size_t size_alloc= strlen(part_name) + MAX_PART_NAME_SIZE;
406 char *ptr= (char*) thd->calloc(size_alloc);
407 DBUG_ENTER("create_default_subpartition_name");
408
409 if (likely(ptr != NULL))
410 my_snprintf(ptr, size_alloc, "%ssp%u", part_name, subpart_no);
411
412 DBUG_RETURN(ptr);
413}
414
415
416/*
417 Set up all the default partitions not set-up by the user in the SQL
418 statement. Also perform a number of checks that the user hasn't tried
419 to use default values where no defaults exists.
420
421 SYNOPSIS
422 set_up_default_partitions()
423 file A reference to a handler of the table
424 info Create info
425 start_no Starting partition number
426
427 RETURN VALUE
428 TRUE Error, attempted default values not possible
429 FALSE Ok, default partitions set-up
430
431 DESCRIPTION
432 The routine uses the underlying handler of the partitioning to define
433 the default number of partitions. For some handlers this requires
434 knowledge of the maximum number of rows to be stored in the table.
435 This routine only accepts HASH and KEY partitioning and thus there is
436 no subpartitioning if this routine is successful.
437 The external routine needing this code is check_partition_info
438*/
439
440bool partition_info::set_up_default_partitions(THD *thd, handler *file,
441 HA_CREATE_INFO *info,
442 uint start_no)
443{
444 uint i;
445 char *default_name;
446 bool result= TRUE;
447 DBUG_ENTER("partition_info::set_up_default_partitions");
448
449 if (part_type != HASH_PARTITION)
450 {
451 const char *error_string;
452 if (part_type == RANGE_PARTITION)
453 error_string= "RANGE";
454 else
455 error_string= "LIST";
456 my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_string);
457 goto end;
458 }
459
460 if ((num_parts == 0) &&
461 ((num_parts= file->get_default_no_partitions(info)) == 0))
462 {
463 my_error(ER_PARTITION_NOT_DEFINED_ERROR, MYF(0), "partitions");
464 goto end;
465 }
466
467 if (unlikely(num_parts > MAX_PARTITIONS))
468 {
469 my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
470 goto end;
471 }
472 if (unlikely((!(default_name= create_default_partition_names(thd, 0,
473 num_parts,
474 start_no)))))
475 goto end;
476 i= 0;
477 do
478 {
479 partition_element *part_elem= new partition_element();
480 if (likely(part_elem != 0 &&
481 (!partitions.push_back(part_elem))))
482 {
483 part_elem->engine_type= default_engine_type;
484 part_elem->partition_name= default_name;
485 default_name+=MAX_PART_NAME_SIZE;
486 }
487 else
488 goto end;
489 } while (++i < num_parts);
490 result= FALSE;
491end:
492 DBUG_RETURN(result);
493}
494
495
496/*
497 Set up all the default subpartitions not set-up by the user in the SQL
498 statement. Also perform a number of checks that the default partitioning
499 becomes an allowed partitioning scheme.
500
501 SYNOPSIS
502 set_up_default_subpartitions()
503 file A reference to a handler of the table
504 info Create info
505
506 RETURN VALUE
507 TRUE Error, attempted default values not possible
508 FALSE Ok, default partitions set-up
509
510 DESCRIPTION
511 The routine uses the underlying handler of the partitioning to define
512 the default number of partitions. For some handlers this requires
513 knowledge of the maximum number of rows to be stored in the table.
514 This routine is only called for RANGE or LIST partitioning and those
515 need to be specified so only subpartitions are specified.
516 The external routine needing this code is check_partition_info
517*/
518
519bool partition_info::set_up_default_subpartitions(THD *thd, handler *file,
520 HA_CREATE_INFO *info)
521{
522 uint i, j;
523 bool result= TRUE;
524 partition_element *part_elem;
525 List_iterator<partition_element> part_it(partitions);
526 DBUG_ENTER("partition_info::set_up_default_subpartitions");
527
528 if (num_subparts == 0)
529 num_subparts= file->get_default_no_partitions(info);
530 if (unlikely((num_parts * num_subparts) > MAX_PARTITIONS))
531 {
532 my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
533 goto end;
534 }
535 i= 0;
536 do
537 {
538 part_elem= part_it++;
539 j= 0;
540 do
541 {
542 partition_element *subpart_elem= new partition_element(part_elem);
543 if (likely(subpart_elem != 0 &&
544 (!part_elem->subpartitions.push_back(subpart_elem))))
545 {
546 char *ptr= create_default_subpartition_name(thd, j,
547 part_elem->partition_name);
548 if (!ptr)
549 goto end;
550 subpart_elem->engine_type= default_engine_type;
551 subpart_elem->partition_name= ptr;
552 }
553 else
554 goto end;
555 } while (++j < num_subparts);
556 } while (++i < num_parts);
557 result= FALSE;
558end:
559 DBUG_RETURN(result);
560}
561
562
563/*
564 Support routine for check_partition_info
565
566 SYNOPSIS
567 set_up_defaults_for_partitioning()
568 file A reference to a handler of the table
569 info Create info
570 start_no Starting partition number
571
572 RETURN VALUE
573 TRUE Error, attempted default values not possible
574 FALSE Ok, default partitions set-up
575
576 DESCRIPTION
577 Set up defaults for partition or subpartition (cannot set-up for both,
578 this will return an error.
579*/
580
581bool partition_info::set_up_defaults_for_partitioning(THD *thd, handler *file,
582 HA_CREATE_INFO *info,
583 uint start_no)
584{
585 DBUG_ENTER("partition_info::set_up_defaults_for_partitioning");
586
587 if (!default_partitions_setup)
588 {
589 default_partitions_setup= TRUE;
590 if (use_default_partitions)
591 DBUG_RETURN(set_up_default_partitions(thd, file, info, start_no));
592 if (is_sub_partitioned() &&
593 use_default_subpartitions)
594 DBUG_RETURN(set_up_default_subpartitions(thd, file, info));
595 }
596 DBUG_RETURN(FALSE);
597}
598
599
600/*
601 Support routine for check_partition_info
602
603 SYNOPSIS
604 find_duplicate_field
605 no parameters
606
607 RETURN VALUE
608 Erroneus field name Error, there are two fields with same name
609 NULL Ok, no field defined twice
610
611 DESCRIPTION
612 Check that the user haven't defined the same field twice in
613 key or column list partitioning.
614*/
615
616const char* partition_info::find_duplicate_field()
617{
618 const char *field_name_outer, *field_name_inner;
619 List_iterator<const char> it_outer(part_field_list);
620 uint num_fields= part_field_list.elements;
621 uint i,j;
622 DBUG_ENTER("partition_info::find_duplicate_field");
623
624 for (i= 0; i < num_fields; i++)
625 {
626 field_name_outer= it_outer++;
627 List_iterator<const char> it_inner(part_field_list);
628 for (j= 0; j < num_fields; j++)
629 {
630 field_name_inner= it_inner++;
631 if (i >= j)
632 continue;
633 if (!(my_strcasecmp(system_charset_info,
634 field_name_outer,
635 field_name_inner)))
636 {
637 DBUG_RETURN(field_name_outer);
638 }
639 }
640 }
641 DBUG_RETURN(NULL);
642}
643
644
645/**
646 @brief Get part_elem and part_id from partition name
647
648 @param partition_name Name of partition to search for.
649 @param file_name[out] Partition file name (part after table name,
650 #P#<part>[#SP#<subpart>]), skipped if NULL.
651 @param part_id[out] Id of found partition or NOT_A_PARTITION_ID.
652
653 @retval Pointer to part_elem of [sub]partition, if not found NULL
654
655 @note Since names of partitions AND subpartitions must be unique,
656 this function searches both partitions and subpartitions and if name of
657 a partition is given for a subpartitioned table, part_elem will be
658 the partition, but part_id will be NOT_A_PARTITION_ID and file_name not set.
659*/
660partition_element *partition_info::get_part_elem(const char *partition_name,
661 char *file_name,
662 size_t file_name_size,
663 uint32 *part_id)
664{
665 List_iterator<partition_element> part_it(partitions);
666 uint i= 0;
667 DBUG_ENTER("partition_info::get_part_elem");
668 DBUG_ASSERT(part_id);
669 *part_id= NOT_A_PARTITION_ID;
670 do
671 {
672 partition_element *part_elem= part_it++;
673 if (is_sub_partitioned())
674 {
675 List_iterator<partition_element> sub_part_it(part_elem->subpartitions);
676 uint j= 0;
677 do
678 {
679 partition_element *sub_part_elem= sub_part_it++;
680 if (!my_strcasecmp(system_charset_info,
681 sub_part_elem->partition_name, partition_name))
682 {
683 if (file_name)
684 if (create_subpartition_name(file_name, file_name_size, "",
685 part_elem->partition_name,
686 partition_name, NORMAL_PART_NAME))
687 DBUG_RETURN(NULL);
688 *part_id= j + (i * num_subparts);
689 DBUG_RETURN(sub_part_elem);
690 }
691 } while (++j < num_subparts);
692
693 /* Naming a partition (first level) on a subpartitioned table. */
694 if (!my_strcasecmp(system_charset_info,
695 part_elem->partition_name, partition_name))
696 DBUG_RETURN(part_elem);
697 }
698 else if (!my_strcasecmp(system_charset_info,
699 part_elem->partition_name, partition_name))
700 {
701 if (file_name)
702 if (create_partition_name(file_name, file_name_size, "",
703 partition_name, NORMAL_PART_NAME, TRUE))
704 DBUG_RETURN(NULL);
705 *part_id= i;
706 DBUG_RETURN(part_elem);
707 }
708 } while (++i < num_parts);
709 DBUG_RETURN(NULL);
710}
711
712
713/**
714 Helper function to find_duplicate_name.
715*/
716
717static const char *get_part_name_from_elem(const char *name, size_t *length,
718 my_bool not_used __attribute__((unused)))
719{
720 *length= strlen(name);
721 return name;
722}
723
724/*
725 A support function to check partition names for duplication in a
726 partitioned table
727
728 SYNOPSIS
729 find_duplicate_name()
730
731 RETURN VALUES
732 NULL Has unique part and subpart names
733 !NULL Pointer to duplicated name
734
735 DESCRIPTION
736 Checks that the list of names in the partitions doesn't contain any
737 duplicated names.
738*/
739
740char *partition_info::find_duplicate_name()
741{
742 HASH partition_names;
743 uint max_names;
744 const uchar *curr_name= NULL;
745 List_iterator<partition_element> parts_it(partitions);
746 partition_element *p_elem;
747
748 DBUG_ENTER("partition_info::find_duplicate_name");
749
750 /*
751 TODO: If table->s->ha_part_data->partition_name_hash.elements is > 0,
752 then we could just return NULL, but that has not been verified.
753 And this only happens when in ALTER TABLE with full table copy.
754 */
755
756 max_names= num_parts;
757 if (is_sub_partitioned())
758 max_names+= num_parts * num_subparts;
759 if (my_hash_init(&partition_names, system_charset_info, max_names, 0, 0,
760 (my_hash_get_key) get_part_name_from_elem, 0, HASH_UNIQUE))
761 {
762 DBUG_ASSERT(0);
763 curr_name= (const uchar*) "Internal failure";
764 goto error;
765 }
766 while ((p_elem= (parts_it++)))
767 {
768 curr_name= (const uchar*) p_elem->partition_name;
769 if (my_hash_insert(&partition_names, curr_name))
770 goto error;
771
772 if (!p_elem->subpartitions.is_empty())
773 {
774 List_iterator<partition_element> subparts_it(p_elem->subpartitions);
775 partition_element *subp_elem;
776 while ((subp_elem= (subparts_it++)))
777 {
778 curr_name= (const uchar*) subp_elem->partition_name;
779 if (my_hash_insert(&partition_names, curr_name))
780 goto error;
781 }
782 }
783 }
784 my_hash_free(&partition_names);
785 DBUG_RETURN(NULL);
786error:
787 my_hash_free(&partition_names);
788 DBUG_RETURN((char*) curr_name);
789}
790
791
792/*
793 A support function to check if a partition element's name is unique
794
795 SYNOPSIS
796 has_unique_name()
797 partition_element element to check
798
799 RETURN VALUES
800 TRUE Has unique name
801 FALSE Doesn't
802*/
803
804bool partition_info::has_unique_name(partition_element *element)
805{
806 DBUG_ENTER("partition_info::has_unique_name");
807
808 const char *name_to_check= element->partition_name;
809 List_iterator<partition_element> parts_it(partitions);
810
811 partition_element *el;
812 while ((el= (parts_it++)))
813 {
814 if (!(my_strcasecmp(system_charset_info, el->partition_name,
815 name_to_check)) && el != element)
816 DBUG_RETURN(FALSE);
817
818 if (!el->subpartitions.is_empty())
819 {
820 partition_element *sub_el;
821 List_iterator<partition_element> subparts_it(el->subpartitions);
822 while ((sub_el= (subparts_it++)))
823 {
824 if (!(my_strcasecmp(system_charset_info, sub_el->partition_name,
825 name_to_check)) && sub_el != element)
826 DBUG_RETURN(FALSE);
827 }
828 }
829 }
830 DBUG_RETURN(TRUE);
831}
832
833void partition_info::vers_set_hist_part(THD *thd)
834{
835 if (vers_info->limit)
836 {
837 ha_partition *hp= (ha_partition*)(table->file);
838 partition_element *next= NULL;
839 List_iterator<partition_element> it(partitions);
840 while (next != vers_info->hist_part)
841 next= it++;
842 ha_rows records= hp->part_records(next);
843 while ((next= it++) != vers_info->now_part)
844 {
845 ha_rows next_records= hp->part_records(next);
846 if (next_records == 0)
847 break;
848 vers_info->hist_part= next;
849 records= next_records;
850 }
851 if (records > vers_info->limit)
852 {
853 if (next == vers_info->now_part)
854 goto warn;
855 vers_info->hist_part= next;
856 }
857 return;
858 }
859
860 if (vers_info->interval.is_set())
861 {
862 if (vers_info->hist_part->range_value > thd->query_start())
863 return;
864
865 partition_element *next= NULL;
866 List_iterator<partition_element> it(partitions);
867 while (next != vers_info->hist_part)
868 next= it++;
869
870 while ((next= it++) != vers_info->now_part)
871 {
872 vers_info->hist_part= next;
873 if (next->range_value > thd->query_start())
874 return;
875 }
876 goto warn;
877 }
878 return;
879warn:
880 my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
881 table->s->db.str, table->s->error_table_name(),
882 vers_info->hist_part->partition_name);
883}
884
885
886bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add)
887{
888 if (!table->versioned())
889 {
890 // frm must be corrupted, normally CREATE/ALTER TABLE checks for that
891 my_error(ER_FILE_CORRUPT, MYF(0), table->s->path.str);
892 return true;
893 }
894
895 DBUG_ASSERT(part_type == VERSIONING_PARTITION);
896 DBUG_ASSERT(table->versioned(VERS_TIMESTAMP));
897 DBUG_ASSERT(num_columns == 1);
898
899 if (!alter_add)
900 {
901 Field *row_end= table->vers_end_field();
902 part_field_list.push_back(row_end->field_name.str, thd->mem_root);
903 DBUG_ASSERT(part_field_list.elements == 1);
904 // needed in handle_list_of_fields()
905 row_end->flags|= GET_FIXED_FIELDS_FLAG;
906 }
907
908 if (alter_add)
909 {
910 List_iterator<partition_element> it(partitions);
911 partition_element *el;
912 for(uint32 id= 0; ((el= it++)); id++)
913 {
914 DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL);
915 /* Newly added element is inserted before AS_OF_NOW. */
916 if (el->id == UINT_MAX32 || el->type() == partition_element::CURRENT)
917 {
918 el->id= id;
919 if (el->type() == partition_element::CURRENT)
920 break;
921 }
922 }
923 }
924 return false;
925}
926
927
928/*
929 Check that the partition/subpartition is setup to use the correct
930 storage engine
931 SYNOPSIS
932 check_engine_condition()
933 p_elem Partition element
934 table_engine_set Have user specified engine on table level
935 inout::engine_type Current engine used
936 inout::first Is it first partition
937 RETURN VALUE
938 TRUE Failed check
939 FALSE Ok
940 DESCRIPTION
941 Specified engine for table and partitions p0 and pn
942 Must be correct both on CREATE and ALTER commands
943 table p0 pn res (0 - OK, 1 - FAIL)
944 - - - 0
945 - - x 1
946 - x - 1
947 - x x 0
948 x - - 0
949 x - x 0
950 x x - 0
951 x x x 0
952 i.e:
953 - All subpartitions must use the same engine
954 AND it must be the same as the partition.
955 - All partitions must use the same engine
956 AND it must be the same as the table.
957 - if one does NOT specify an engine on the table level
958 then one must either NOT specify any engine on any
959 partition/subpartition OR for ALL partitions/subpartitions
960 Note:
961 When ALTER a table, the engines are already set for all levels
962 (table, all partitions and subpartitions). So if one want to
963 change the storage engine, one must specify it on the table level
964
965*/
966
967static bool check_engine_condition(partition_element *p_elem,
968 bool table_engine_set,
969 handlerton **engine_type,
970 bool *first)
971{
972 DBUG_ENTER("check_engine_condition");
973
974 DBUG_PRINT("enter", ("p_eng %s t_eng %s t_eng_set %u first %u state %u",
975 ha_resolve_storage_engine_name(p_elem->engine_type),
976 ha_resolve_storage_engine_name(*engine_type),
977 table_engine_set, *first, p_elem->part_state));
978 if (*first && !table_engine_set)
979 {
980 *engine_type= p_elem->engine_type;
981 DBUG_PRINT("info", ("setting table_engine = %s",
982 ha_resolve_storage_engine_name(*engine_type)));
983 }
984 *first= FALSE;
985 if ((table_engine_set &&
986 (p_elem->engine_type != (*engine_type) &&
987 p_elem->engine_type)) ||
988 (!table_engine_set &&
989 p_elem->engine_type != (*engine_type)))
990 {
991 DBUG_RETURN(TRUE);
992 }
993
994 DBUG_RETURN(FALSE);
995}
996
997
998/*
999 Check engine mix that it is correct
1000 Current limitation is that all partitions and subpartitions
1001 must use the same storage engine.
1002 SYNOPSIS
1003 check_engine_mix()
1004 inout::engine_type Current engine used
1005 table_engine_set Have user specified engine on table level
1006 RETURN VALUE
1007 TRUE Error, mixed engines
1008 FALSE Ok, no mixed engines
1009 DESCRIPTION
1010 Current check verifies only that all handlers are the same.
1011 Later this check will be more sophisticated.
1012 (specified partition handler ) specified table handler
1013 (MYISAM, MYISAM) - OK
1014 (MYISAM, -) - NOT OK
1015 (MYISAM, -) MYISAM OK
1016 (- , MYISAM) - NOT OK
1017 (- , -) MYISAM OK
1018 (-,-) - OK
1019*/
1020
1021bool partition_info::check_engine_mix(handlerton *engine_type,
1022 bool table_engine_set)
1023{
1024 handlerton *old_engine_type= engine_type;
1025 bool first= TRUE;
1026 uint n_parts= partitions.elements;
1027 DBUG_ENTER("partition_info::check_engine_mix");
1028 DBUG_PRINT("info", ("in: engine_type = %s, table_engine_set = %u",
1029 ha_resolve_storage_engine_name(engine_type),
1030 table_engine_set));
1031 if (n_parts)
1032 {
1033 List_iterator<partition_element> part_it(partitions);
1034 uint i= 0;
1035 do
1036 {
1037 partition_element *part_elem= part_it++;
1038 DBUG_PRINT("info", ("part = %d engine = %s table_engine_set %u",
1039 i, ha_resolve_storage_engine_name(part_elem->engine_type),
1040 table_engine_set));
1041 if (is_sub_partitioned() &&
1042 part_elem->subpartitions.elements)
1043 {
1044 uint n_subparts= part_elem->subpartitions.elements;
1045 uint j= 0;
1046 List_iterator<partition_element> sub_it(part_elem->subpartitions);
1047 do
1048 {
1049 partition_element *sub_elem= sub_it++;
1050 DBUG_PRINT("info", ("sub = %d engine = %s table_engie_set %u",
1051 j, ha_resolve_storage_engine_name(sub_elem->engine_type),
1052 table_engine_set));
1053 if (check_engine_condition(sub_elem, table_engine_set,
1054 &engine_type, &first))
1055 goto error;
1056 } while (++j < n_subparts);
1057 /* ensure that the partition also has correct engine */
1058 if (check_engine_condition(part_elem, table_engine_set,
1059 &engine_type, &first))
1060 goto error;
1061 }
1062 else if (check_engine_condition(part_elem, table_engine_set,
1063 &engine_type, &first))
1064 goto error;
1065 } while (++i < n_parts);
1066 }
1067 DBUG_PRINT("info", ("engine_type = %s",
1068 ha_resolve_storage_engine_name(engine_type)));
1069 if (!engine_type)
1070 engine_type= old_engine_type;
1071 if (engine_type->flags & HTON_NO_PARTITION)
1072 {
1073 my_error(ER_PARTITION_MERGE_ERROR, MYF(0));
1074 DBUG_RETURN(TRUE);
1075 }
1076 DBUG_PRINT("info", ("out: engine_type = %s",
1077 ha_resolve_storage_engine_name(engine_type)));
1078 DBUG_ASSERT(engine_type != partition_hton);
1079 DBUG_RETURN(FALSE);
1080error:
1081 /*
1082 Mixed engines not yet supported but when supported it will need
1083 the partition handler
1084 */
1085 DBUG_RETURN(TRUE);
1086}
1087
1088
1089/**
1090 Check if we allow DATA/INDEX DIRECTORY, if not warn and set them to NULL.
1091
1092 @param thd THD also containing sql_mode (looks from MODE_NO_DIR_IN_CREATE).
1093 @param part_elem partition_element to check.
1094*/
1095static void warn_if_dir_in_part_elem(THD *thd, partition_element *part_elem)
1096{
1097 if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
1098 {
1099 if (part_elem->data_file_name)
1100 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1101 WARN_OPTION_IGNORED,
1102 ER_THD(thd, WARN_OPTION_IGNORED),
1103 "DATA DIRECTORY");
1104 if (part_elem->index_file_name)
1105 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1106 WARN_OPTION_IGNORED,
1107 ER_THD(thd, WARN_OPTION_IGNORED),
1108 "INDEX DIRECTORY");
1109 part_elem->data_file_name= part_elem->index_file_name= NULL;
1110 }
1111}
1112
1113
1114/*
1115 This code is used early in the CREATE TABLE and ALTER TABLE process.
1116
1117 SYNOPSIS
1118 check_partition_info()
1119 thd Thread object
1120 eng_type Return value for used engine in partitions
1121 file A reference to a handler of the table
1122 info Create info
1123 add_or_reorg_part Is it ALTER TABLE ADD/REORGANIZE command
1124
1125 RETURN VALUE
1126 TRUE Error, something went wrong
1127 FALSE Ok, full partition data structures are now generated
1128
1129 DESCRIPTION
1130 We will check that the partition info requested is possible to set-up in
1131 this version. This routine is an extension of the parser one could say.
1132 If defaults were used we will generate default data structures for all
1133 partitions.
1134
1135*/
1136
1137bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
1138 handler *file, HA_CREATE_INFO *info,
1139 partition_info *add_or_reorg_part)
1140{
1141 handlerton *table_engine= default_engine_type;
1142 uint i, tot_partitions;
1143 bool result= TRUE, table_engine_set;
1144 const char *same_name;
1145 uint32 hist_parts= 0;
1146 uint32 now_parts= 0;
1147 DBUG_ENTER("partition_info::check_partition_info");
1148 DBUG_ASSERT(default_engine_type != partition_hton);
1149
1150 DBUG_PRINT("info", ("default table_engine = %s",
1151 ha_resolve_storage_engine_name(table_engine)));
1152 if (!add_or_reorg_part)
1153 {
1154 int err= 0;
1155
1156 /* Check for partition expression. */
1157 if (!list_of_part_fields)
1158 {
1159 DBUG_ASSERT(part_expr);
1160 err= part_expr->walk(&Item::check_partition_func_processor, 0, NULL);
1161 }
1162
1163 /* Check for sub partition expression. */
1164 if (!err && is_sub_partitioned() && !list_of_subpart_fields)
1165 {
1166 DBUG_ASSERT(subpart_expr);
1167 err= subpart_expr->walk(&Item::check_partition_func_processor, 0,
1168 NULL);
1169 }
1170
1171 if (err)
1172 {
1173 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
1174 goto end;
1175 }
1176 if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
1177 fix_parser_data(thd))
1178 goto end;
1179 }
1180 if (unlikely(!is_sub_partitioned() &&
1181 !(use_default_subpartitions && use_default_num_subpartitions)))
1182 {
1183 my_error(ER_SUBPARTITION_ERROR, MYF(0));
1184 goto end;
1185 }
1186 if (unlikely(is_sub_partitioned() &&
1187 (!(part_type == RANGE_PARTITION ||
1188 part_type == LIST_PARTITION ||
1189 part_type == VERSIONING_PARTITION))))
1190 {
1191 /* Only RANGE and LIST partitioning can be subpartitioned */
1192 my_error(ER_SUBPARTITION_ERROR, MYF(0));
1193 goto end;
1194 }
1195 if (unlikely(set_up_defaults_for_partitioning(thd, file, info, (uint)0)))
1196 goto end;
1197 if (!(tot_partitions= get_tot_partitions()))
1198 {
1199 my_error(ER_PARTITION_NOT_DEFINED_ERROR, MYF(0), "partitions");
1200 goto end;
1201 }
1202 if (unlikely(tot_partitions > MAX_PARTITIONS))
1203 {
1204 my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
1205 goto end;
1206 }
1207 /*
1208 if NOT specified ENGINE = <engine>:
1209 If Create, always use create_info->db_type
1210 else, use previous tables db_type
1211 either ALL or NONE partition should be set to
1212 default_engine_type when not table_engine_set
1213 Note: after a table is created its storage engines for
1214 the table and all partitions/subpartitions are set.
1215 So when ALTER it is already set on table level
1216 */
1217 if (info && info->used_fields & HA_CREATE_USED_ENGINE)
1218 {
1219 table_engine_set= TRUE;
1220 table_engine= info->db_type;
1221 /* if partition_hton, use thd->lex->create_info */
1222 if (table_engine == partition_hton)
1223 table_engine= thd->lex->create_info.db_type;
1224 DBUG_ASSERT(table_engine != partition_hton);
1225 DBUG_PRINT("info", ("Using table_engine = %s",
1226 ha_resolve_storage_engine_name(table_engine)));
1227 }
1228 else
1229 {
1230 table_engine_set= FALSE;
1231 if (thd->lex->sql_command != SQLCOM_CREATE_TABLE)
1232 {
1233 table_engine_set= TRUE;
1234 DBUG_PRINT("info", ("No create, table_engine = %s",
1235 ha_resolve_storage_engine_name(table_engine)));
1236 DBUG_ASSERT(table_engine && table_engine != partition_hton);
1237 }
1238 }
1239
1240 if (part_field_list.elements > 0 &&
1241 (same_name= find_duplicate_field()))
1242 {
1243 my_error(ER_SAME_NAME_PARTITION_FIELD, MYF(0), same_name);
1244 goto end;
1245 }
1246 if ((same_name= find_duplicate_name()))
1247 {
1248 my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
1249 goto end;
1250 }
1251
1252 if (part_type == VERSIONING_PARTITION)
1253 {
1254 DBUG_ASSERT(vers_info);
1255 if (num_parts < 2 || !vers_info->now_part)
1256 {
1257 DBUG_ASSERT(info);
1258 DBUG_ASSERT(info->alias.str);
1259 my_error(ER_VERS_WRONG_PARTS, MYF(0), info->alias.str);
1260 goto end;
1261 }
1262 DBUG_ASSERT(num_parts == partitions.elements);
1263 }
1264 i= 0;
1265 {
1266 List_iterator<partition_element> part_it(partitions);
1267 uint num_parts_not_set= 0;
1268 uint prev_num_subparts_not_set= num_subparts + 1;
1269 do
1270 {
1271 partition_element *part_elem= part_it++;
1272 warn_if_dir_in_part_elem(thd, part_elem);
1273 if (!is_sub_partitioned())
1274 {
1275 if (part_elem->engine_type == NULL)
1276 {
1277 num_parts_not_set++;
1278 part_elem->engine_type= default_engine_type;
1279 }
1280 if (check_table_name(part_elem->partition_name,
1281 strlen(part_elem->partition_name), FALSE))
1282 {
1283 my_error(ER_WRONG_PARTITION_NAME, MYF(0));
1284 goto end;
1285 }
1286 DBUG_PRINT("info", ("part = %d engine = %s",
1287 i, ha_resolve_storage_engine_name(part_elem->engine_type)));
1288 }
1289 else
1290 {
1291 uint j= 0;
1292 uint num_subparts_not_set= 0;
1293 List_iterator<partition_element> sub_it(part_elem->subpartitions);
1294 partition_element *sub_elem;
1295 do
1296 {
1297 sub_elem= sub_it++;
1298 warn_if_dir_in_part_elem(thd, sub_elem);
1299 if (check_table_name(sub_elem->partition_name,
1300 strlen(sub_elem->partition_name), FALSE))
1301 {
1302 my_error(ER_WRONG_PARTITION_NAME, MYF(0));
1303 goto end;
1304 }
1305 if (sub_elem->engine_type == NULL)
1306 {
1307 if (part_elem->engine_type != NULL)
1308 sub_elem->engine_type= part_elem->engine_type;
1309 else
1310 {
1311 sub_elem->engine_type= default_engine_type;
1312 num_subparts_not_set++;
1313 }
1314 }
1315 DBUG_PRINT("info", ("part = %d sub = %d engine = %s", i, j,
1316 ha_resolve_storage_engine_name(sub_elem->engine_type)));
1317 } while (++j < num_subparts);
1318
1319 if (prev_num_subparts_not_set == (num_subparts + 1) &&
1320 (num_subparts_not_set == 0 ||
1321 num_subparts_not_set == num_subparts))
1322 prev_num_subparts_not_set= num_subparts_not_set;
1323
1324 if (!table_engine_set &&
1325 prev_num_subparts_not_set != num_subparts_not_set)
1326 {
1327 DBUG_PRINT("info", ("num_subparts_not_set = %u num_subparts = %u",
1328 num_subparts_not_set, num_subparts));
1329 my_error(ER_MIX_HANDLER_ERROR, MYF(0));
1330 goto end;
1331 }
1332
1333 if (part_elem->engine_type == NULL)
1334 {
1335 if (num_subparts_not_set == 0)
1336 part_elem->engine_type= sub_elem->engine_type;
1337 else
1338 {
1339 num_parts_not_set++;
1340 part_elem->engine_type= default_engine_type;
1341 }
1342 }
1343 }
1344 if (part_type == VERSIONING_PARTITION)
1345 {
1346 if (part_elem->type() == partition_element::HISTORY)
1347 {
1348 hist_parts++;
1349 }
1350 else
1351 {
1352 DBUG_ASSERT(part_elem->type() == partition_element::CURRENT);
1353 now_parts++;
1354 }
1355 }
1356 } while (++i < num_parts);
1357 if (!table_engine_set &&
1358 num_parts_not_set != 0 &&
1359 num_parts_not_set != num_parts)
1360 {
1361 DBUG_PRINT("info", ("num_parts_not_set = %u num_parts = %u",
1362 num_parts_not_set, num_subparts));
1363 my_error(ER_MIX_HANDLER_ERROR, MYF(0));
1364 goto end;
1365 }
1366 }
1367 if (unlikely(check_engine_mix(table_engine, table_engine_set)))
1368 {
1369 my_error(ER_MIX_HANDLER_ERROR, MYF(0));
1370 goto end;
1371 }
1372
1373 if (hist_parts > 1)
1374 {
1375 if (vers_info->limit == 0 && !vers_info->interval.is_set())
1376 {
1377 push_warning_printf(thd,
1378 Sql_condition::WARN_LEVEL_WARN,
1379 WARN_VERS_PARAMETERS,
1380 ER_THD(thd, WARN_VERS_PARAMETERS),
1381 "no rotation condition for multiple HISTORY partitions.");
1382 }
1383 }
1384 if (unlikely(now_parts > 1))
1385 {
1386 my_error(ER_VERS_WRONG_PARTS, MYF(0), info->alias.str);
1387 goto end;
1388 }
1389
1390
1391 DBUG_ASSERT(table_engine != partition_hton &&
1392 default_engine_type == table_engine);
1393 if (eng_type)
1394 *eng_type= table_engine;
1395
1396
1397 /*
1398 We need to check all constant expressions that they are of the correct
1399 type and that they are increasing for ranges and not overlapping for
1400 list constants.
1401 */
1402
1403 if (add_or_reorg_part)
1404 {
1405 if (unlikely(part_type == VERSIONING_PARTITION &&
1406 vers_setup_expression(thd, add_or_reorg_part->partitions.elements)))
1407 goto end;
1408 if (check_constants(thd, this))
1409 goto end;
1410 }
1411
1412 result= FALSE;
1413end:
1414 DBUG_RETURN(result);
1415}
1416
1417
1418/*
1419 Print error for no partition found
1420
1421 SYNOPSIS
1422 print_no_partition_found()
1423 table Table object
1424
1425 RETURN VALUES
1426*/
1427
1428void partition_info::print_no_partition_found(TABLE *table_arg, myf errflag)
1429{
1430 char buf[100];
1431 char *buf_ptr= (char*)&buf;
1432 TABLE_LIST table_list;
1433 THD *thd= current_thd;
1434
1435 bzero(&table_list, sizeof(table_list));
1436 table_list.db= table_arg->s->db;
1437 table_list.table_name= table_arg->s->table_name;
1438
1439 if (check_single_table_access(thd,
1440 SELECT_ACL, &table_list, TRUE))
1441 {
1442 my_message(ER_NO_PARTITION_FOR_GIVEN_VALUE,
1443 ER_THD(thd, ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT), errflag);
1444 }
1445 else
1446 {
1447 if (column_list)
1448 buf_ptr= (char*)"from column_list";
1449 else
1450 {
1451 my_bitmap_map *old_map= dbug_tmp_use_all_columns(table_arg, table_arg->read_set);
1452 if (part_expr->null_value)
1453 buf_ptr= (char*)"NULL";
1454 else
1455 longlong10_to_str(err_value, buf,
1456 part_expr->unsigned_flag ? 10 : -10);
1457 dbug_tmp_restore_column_map(table_arg->read_set, old_map);
1458 }
1459 my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, errflag, buf_ptr);
1460 }
1461}
1462
1463
1464/*
1465 Set fields related to partition expression
1466 SYNOPSIS
1467 set_part_expr()
1468 start_token Start of partition function string
1469 item_ptr Pointer to item tree
1470 end_token End of partition function string
1471 is_subpart Subpartition indicator
1472 RETURN VALUES
1473 TRUE Memory allocation error
1474 FALSE Success
1475*/
1476
1477bool partition_info::set_part_expr(THD *thd, char *start_token, Item *item_ptr,
1478 char *end_token, bool is_subpart)
1479{
1480 size_t expr_len= end_token - start_token;
1481 char *func_string= (char*) thd->memdup(start_token, expr_len);
1482
1483 if (unlikely(!func_string))
1484 return TRUE;
1485
1486 if (is_subpart)
1487 {
1488 list_of_subpart_fields= FALSE;
1489 subpart_expr= item_ptr;
1490 }
1491 else
1492 {
1493 list_of_part_fields= FALSE;
1494 part_expr= item_ptr;
1495 }
1496 return FALSE;
1497}
1498
1499
1500/*
1501 Check that partition fields and subpartition fields are not too long
1502
1503 SYNOPSIS
1504 check_partition_field_length()
1505
1506 RETURN VALUES
1507 TRUE Total length was too big
1508 FALSE Length is ok
1509*/
1510
1511bool partition_info::check_partition_field_length()
1512{
1513 uint store_length= 0;
1514 uint i;
1515 DBUG_ENTER("partition_info::check_partition_field_length");
1516
1517 for (i= 0; i < num_part_fields; i++)
1518 store_length+= get_partition_field_store_length(part_field_array[i]);
1519 if (store_length > MAX_KEY_LENGTH)
1520 DBUG_RETURN(TRUE);
1521 store_length= 0;
1522 for (i= 0; i < num_subpart_fields; i++)
1523 store_length+= get_partition_field_store_length(subpart_field_array[i]);
1524 if (store_length > MAX_KEY_LENGTH)
1525 DBUG_RETURN(TRUE);
1526 DBUG_RETURN(FALSE);
1527}
1528
1529
1530/*
1531 Set up buffers and arrays for fields requiring preparation
1532 SYNOPSIS
1533 set_up_charset_field_preps()
1534
1535 RETURN VALUES
1536 TRUE Memory Allocation error
1537 FALSE Success
1538
1539 DESCRIPTION
1540 Set up arrays and buffers for fields that require special care for
1541 calculation of partition id. This is used for string fields with
1542 variable length or string fields with fixed length that isn't using
1543 the binary collation.
1544*/
1545
1546bool partition_info::set_up_charset_field_preps(THD *thd)
1547{
1548 Field *field, **ptr;
1549 uchar **char_ptrs;
1550 unsigned i;
1551 size_t size;
1552 uint tot_fields= 0;
1553 uint tot_part_fields= 0;
1554 uint tot_subpart_fields= 0;
1555 DBUG_ENTER("set_up_charset_field_preps");
1556
1557 if (!(part_type == HASH_PARTITION &&
1558 list_of_part_fields) &&
1559 check_part_func_fields(part_field_array, FALSE))
1560 {
1561 ptr= part_field_array;
1562 /* Set up arrays and buffers for those fields */
1563 while ((field= *(ptr++)))
1564 {
1565 if (field_is_partition_charset(field))
1566 {
1567 tot_part_fields++;
1568 tot_fields++;
1569 }
1570 }
1571 size= tot_part_fields * sizeof(char*);
1572 if (!(char_ptrs= (uchar**)thd->calloc(size)))
1573 goto error;
1574 part_field_buffers= char_ptrs;
1575 if (!(char_ptrs= (uchar**)thd->calloc(size)))
1576 goto error;
1577 restore_part_field_ptrs= char_ptrs;
1578 size= (tot_part_fields + 1) * sizeof(Field*);
1579 if (!(char_ptrs= (uchar**)thd->alloc(size)))
1580 goto error;
1581 part_charset_field_array= (Field**)char_ptrs;
1582 ptr= part_field_array;
1583 i= 0;
1584 while ((field= *(ptr++)))
1585 {
1586 if (field_is_partition_charset(field))
1587 {
1588 uchar *field_buf;
1589 size= field->pack_length();
1590 if (!(field_buf= (uchar*) thd->calloc(size)))
1591 goto error;
1592 part_charset_field_array[i]= field;
1593 part_field_buffers[i++]= field_buf;
1594 }
1595 }
1596 part_charset_field_array[i]= NULL;
1597 }
1598 if (is_sub_partitioned() && !list_of_subpart_fields &&
1599 check_part_func_fields(subpart_field_array, FALSE))
1600 {
1601 /* Set up arrays and buffers for those fields */
1602 ptr= subpart_field_array;
1603 while ((field= *(ptr++)))
1604 {
1605 if (field_is_partition_charset(field))
1606 {
1607 tot_subpart_fields++;
1608 tot_fields++;
1609 }
1610 }
1611 size= tot_subpart_fields * sizeof(char*);
1612 if (!(char_ptrs= (uchar**) thd->calloc(size)))
1613 goto error;
1614 subpart_field_buffers= char_ptrs;
1615 if (!(char_ptrs= (uchar**) thd->calloc(size)))
1616 goto error;
1617 restore_subpart_field_ptrs= char_ptrs;
1618 size= (tot_subpart_fields + 1) * sizeof(Field*);
1619 if (!(char_ptrs= (uchar**) thd->alloc(size)))
1620 goto error;
1621 subpart_charset_field_array= (Field**)char_ptrs;
1622 ptr= subpart_field_array;
1623 i= 0;
1624 while ((field= *(ptr++)))
1625 {
1626 uchar *UNINIT_VAR(field_buf);
1627
1628 if (!field_is_partition_charset(field))
1629 continue;
1630 size= field->pack_length();
1631 if (!(field_buf= (uchar*) thd->calloc(size)))
1632 goto error;
1633 subpart_charset_field_array[i]= field;
1634 subpart_field_buffers[i++]= field_buf;
1635 }
1636 subpart_charset_field_array[i]= NULL;
1637 }
1638 DBUG_RETURN(FALSE);
1639error:
1640 DBUG_RETURN(TRUE);
1641}
1642
1643
1644/*
1645 Check if path does not contain mysql data home directory
1646 for partition elements with data directory and index directory
1647
1648 SYNOPSIS
1649 check_partition_dirs()
1650 part_info partition_info struct
1651
1652 RETURN VALUES
1653 0 ok
1654 1 error
1655*/
1656
1657bool check_partition_dirs(partition_info *part_info)
1658{
1659 if (!part_info)
1660 return 0;
1661
1662 partition_element *part_elem;
1663 List_iterator<partition_element> part_it(part_info->partitions);
1664 while ((part_elem= part_it++))
1665 {
1666 if (part_elem->subpartitions.elements)
1667 {
1668 List_iterator<partition_element> sub_it(part_elem->subpartitions);
1669 partition_element *subpart_elem;
1670 while ((subpart_elem= sub_it++))
1671 {
1672 if (unlikely(error_if_data_home_dir(subpart_elem->data_file_name,
1673 "DATA DIRECTORY")) ||
1674 unlikely(error_if_data_home_dir(subpart_elem->index_file_name,
1675 "INDEX DIRECTORY")))
1676 return 1;
1677 }
1678 }
1679 else
1680 {
1681 if (unlikely(error_if_data_home_dir(part_elem->data_file_name,
1682 "DATA DIRECTORY")) ||
1683 unlikely(error_if_data_home_dir(part_elem->index_file_name,
1684 "INDEX DIRECTORY")))
1685 return 1;
1686 }
1687 }
1688 return 0;
1689}
1690
1691
1692/**
1693 Check what kind of error to report
1694
1695 @param use_subpart_expr Use the subpart_expr instead of part_expr
1696 @param part_str Name of partition to report error (or NULL)
1697*/
1698void partition_info::report_part_expr_error(bool use_subpart_expr)
1699{
1700 Item *expr= part_expr;
1701 DBUG_ENTER("partition_info::report_part_expr_error");
1702 if (use_subpart_expr)
1703 expr= subpart_expr;
1704
1705 if (expr->type() == Item::FIELD_ITEM)
1706 {
1707 partition_type type= part_type;
1708 bool list_of_fields= list_of_part_fields;
1709 Item_field *item_field= (Item_field*) expr;
1710 /*
1711 The expression consists of a single field.
1712 It must be of integer type unless KEY or COLUMNS partitioning.
1713 */
1714 if (use_subpart_expr)
1715 {
1716 type= subpart_type;
1717 list_of_fields= list_of_subpart_fields;
1718 }
1719 if (!column_list &&
1720 item_field->field &&
1721 item_field->field->result_type() != INT_RESULT &&
1722 !(type == HASH_PARTITION && list_of_fields))
1723 {
1724 my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
1725 item_field->name.str);
1726 DBUG_VOID_RETURN;
1727 }
1728 }
1729 if (use_subpart_expr)
1730 my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), "SUBPARTITION");
1731 else
1732 my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), "PARTITION");
1733 DBUG_VOID_RETURN;
1734}
1735
1736
1737/*
1738 Create a new column value in current list with maxvalue
1739 Called from parser
1740
1741 SYNOPSIS
1742 add_max_value()
1743 RETURN
1744 TRUE Error
1745 FALSE Success
1746*/
1747
1748int partition_info::add_max_value(THD *thd)
1749{
1750 DBUG_ENTER("partition_info::add_max_value");
1751
1752 part_column_list_val *col_val;
1753 /*
1754 Makes for LIST COLUMNS 'num_columns' DEFAULT tuples, 1 tuple for RANGEs
1755 */
1756 uint max_val= (num_columns && part_type == LIST_PARTITION) ?
1757 num_columns : 1;
1758 for (uint i= 0; i < max_val; i++)
1759 {
1760 if (!(col_val= add_column_value(thd)))
1761 {
1762 DBUG_RETURN(TRUE);
1763 }
1764 col_val->max_value= TRUE;
1765 }
1766 DBUG_RETURN(FALSE);
1767}
1768
1769/*
1770 Create a new column value in current list
1771 Called from parser
1772
1773 SYNOPSIS
1774 add_column_value()
1775 RETURN
1776 >0 A part_column_list_val object which have been
1777 inserted into its list
1778 0 Memory allocation failure
1779*/
1780
1781part_column_list_val *partition_info::add_column_value(THD *thd)
1782{
1783 uint max_val= num_columns ? num_columns : MAX_REF_PARTS;
1784 DBUG_ENTER("add_column_value");
1785 DBUG_PRINT("enter", ("num_columns = %u, curr_list_object %u, max_val = %u",
1786 num_columns, curr_list_object, max_val));
1787 if (curr_list_object < max_val)
1788 {
1789 curr_list_val->added_items++;
1790 DBUG_RETURN(&curr_list_val->col_val_array[curr_list_object++]);
1791 }
1792 if (!num_columns && part_type == LIST_PARTITION)
1793 {
1794 /*
1795 We're trying to add more than MAX_REF_PARTS, this can happen
1796 in ALTER TABLE using List partitions where the first partition
1797 uses VALUES IN (1,2,3...,17) where the number of fields in
1798 the list is more than MAX_REF_PARTS, in this case we know
1799 that the number of columns must be 1 and we thus reorganize
1800 into the structure used for 1 column. After this we call
1801 ourselves recursively which should always succeed.
1802 */
1803 num_columns= curr_list_object;
1804 if (!reorganize_into_single_field_col_val(thd))
1805 {
1806 if (!init_column_part(thd))
1807 DBUG_RETURN(add_column_value(thd));
1808 }
1809 DBUG_RETURN(NULL);
1810 }
1811 if (column_list)
1812 {
1813 my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
1814 }
1815 else
1816 {
1817 if (part_type == RANGE_PARTITION)
1818 my_error(ER_TOO_MANY_VALUES_ERROR, MYF(0), "RANGE");
1819 else
1820 my_error(ER_TOO_MANY_VALUES_ERROR, MYF(0), "LIST");
1821 }
1822 DBUG_RETURN(NULL);
1823}
1824
1825
1826/*
1827 Initialise part_elem_value object at setting of a new object
1828 (Helper functions to functions called by parser)
1829
1830 SYNOPSIS
1831 init_col_val
1832 col_val Column value object to be initialised
1833 item Item object representing column value
1834
1835 RETURN VALUES
1836 TRUE Failure
1837 FALSE Success
1838*/
1839void partition_info::init_col_val(part_column_list_val *col_val, Item *item)
1840{
1841 DBUG_ENTER("partition_info::init_col_val");
1842
1843 col_val->item_expression= item;
1844 col_val->null_value= item->null_value;
1845 if (item->result_type() == INT_RESULT)
1846 {
1847 /*
1848 This could be both column_list partitioning and function
1849 partitioning, but it doesn't hurt to set the function
1850 partitioning flags about unsignedness.
1851 */
1852 curr_list_val->value= item->val_int();
1853 curr_list_val->unsigned_flag= TRUE;
1854 if (!item->unsigned_flag &&
1855 curr_list_val->value < 0)
1856 curr_list_val->unsigned_flag= FALSE;
1857 if (!curr_list_val->unsigned_flag)
1858 curr_part_elem->signed_flag= TRUE;
1859 }
1860 col_val->part_info= NULL;
1861 DBUG_VOID_RETURN;
1862}
1863/*
1864 Add a column value in VALUES LESS THAN or VALUES IN
1865 (Called from parser)
1866
1867 SYNOPSIS
1868 add_column_list_value()
1869 lex Parser's lex object
1870 thd Thread object
1871 item Item object representing column value
1872
1873 RETURN VALUES
1874 TRUE Failure
1875 FALSE Success
1876*/
1877bool partition_info::add_column_list_value(THD *thd, Item *item)
1878{
1879 part_column_list_val *col_val;
1880 Name_resolution_context *context= &thd->lex->current_select->context;
1881 TABLE_LIST *save_list= context->table_list;
1882 const char *save_where= thd->where;
1883 DBUG_ENTER("partition_info::add_column_list_value");
1884
1885 if (part_type == LIST_PARTITION &&
1886 num_columns == 1U)
1887 {
1888 if (init_column_part(thd))
1889 {
1890 DBUG_RETURN(TRUE);
1891 }
1892 }
1893
1894 context->table_list= 0;
1895 if (column_list)
1896 thd->where= "field list";
1897 else
1898 thd->where= "partition function";
1899
1900 if (item->walk(&Item::check_partition_func_processor, 0, NULL))
1901 {
1902 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
1903 DBUG_RETURN(TRUE);
1904 }
1905 if (item->fix_fields(thd, (Item**)0) ||
1906 ((context->table_list= save_list), FALSE) ||
1907 (!item->const_item()))
1908 {
1909 context->table_list= save_list;
1910 thd->where= save_where;
1911 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
1912 DBUG_RETURN(TRUE);
1913 }
1914 thd->where= save_where;
1915
1916 if (!(col_val= add_column_value(thd)))
1917 {
1918 DBUG_RETURN(TRUE);
1919 }
1920 init_col_val(col_val, item);
1921 DBUG_RETURN(FALSE);
1922}
1923
1924/*
1925 Initialise part_info object for receiving a set of column values
1926 for a partition, called when parser reaches VALUES LESS THAN or
1927 VALUES IN.
1928
1929 SYNOPSIS
1930 init_column_part()
1931 lex Parser's lex object
1932
1933 RETURN VALUES
1934 TRUE Failure
1935 FALSE Success
1936*/
1937bool partition_info::init_column_part(THD *thd)
1938{
1939 partition_element *p_elem= curr_part_elem;
1940 part_column_list_val *col_val_array;
1941 part_elem_value *list_val;
1942 uint loc_num_columns;
1943 DBUG_ENTER("partition_info::init_column_part");
1944
1945 if (!(list_val=
1946 (part_elem_value*) thd->calloc(sizeof(part_elem_value))) ||
1947 p_elem->list_val_list.push_back(list_val, thd->mem_root))
1948 DBUG_RETURN(TRUE);
1949
1950 if (num_columns)
1951 loc_num_columns= num_columns;
1952 else
1953 loc_num_columns= MAX_REF_PARTS;
1954 if (!(col_val_array=
1955 (part_column_list_val*) thd->calloc(loc_num_columns *
1956 sizeof(part_column_list_val))))
1957 DBUG_RETURN(TRUE);
1958
1959 list_val->col_val_array= col_val_array;
1960 list_val->added_items= 0;
1961 curr_list_val= list_val;
1962 curr_list_object= 0;
1963 DBUG_RETURN(FALSE);
1964}
1965
1966/*
1967 In the case of ALTER TABLE ADD/REORGANIZE PARTITION for LIST
1968 partitions we can specify list values as:
1969 VALUES IN (v1, v2,,,, v17) if we're using the first partitioning
1970 variant with a function or a column list partitioned table with
1971 one partition field. In this case the parser knows not the
1972 number of columns start with and allocates MAX_REF_PARTS in the
1973 array. If we try to allocate something beyond MAX_REF_PARTS we
1974 will call this function to reorganize into a structure with
1975 num_columns = 1. Also when the parser knows that we used LIST
1976 partitioning and we used a VALUES IN like above where number of
1977 values was smaller than MAX_REF_PARTS or equal, then we will
1978 reorganize after discovering this in the parser.
1979
1980 SYNOPSIS
1981 reorganize_into_single_field_col_val()
1982
1983 RETURN VALUES
1984 TRUE Failure
1985 FALSE Success
1986*/
1987
1988int partition_info::reorganize_into_single_field_col_val(THD *thd)
1989{
1990 part_column_list_val *col_val, *new_col_val;
1991 part_elem_value *val= curr_list_val;
1992 uint loc_num_columns= num_columns;
1993 uint i;
1994 DBUG_ENTER("partition_info::reorganize_into_single_field_col_val");
1995
1996 num_columns= 1;
1997 val->added_items= 1U;
1998 col_val= &val->col_val_array[0];
1999 init_col_val(col_val, col_val->item_expression);
2000 for (i= 1; i < loc_num_columns; i++)
2001 {
2002 col_val= &val->col_val_array[i];
2003 DBUG_ASSERT(part_type == LIST_PARTITION);
2004 if (init_column_part(thd))
2005 {
2006 DBUG_RETURN(TRUE);
2007 }
2008 if (!(new_col_val= add_column_value(thd)))
2009 {
2010 DBUG_RETURN(TRUE);
2011 }
2012 memcpy(new_col_val, col_val, sizeof(*col_val));
2013 init_col_val(new_col_val, col_val->item_expression);
2014 }
2015 curr_list_val= val;
2016 DBUG_RETURN(FALSE);
2017}
2018
2019/*
2020 This function handles the case of function-based partitioning.
2021 It fixes some data structures created in the parser and puts
2022 them in the format required by the rest of the partitioning
2023 code.
2024
2025 SYNOPSIS
2026 fix_partition_values()
2027 thd Thread object
2028 col_val Array of one value
2029 part_elem The partition instance
2030 part_id Id of partition instance
2031
2032 RETURN VALUES
2033 TRUE Failure
2034 FALSE Success
2035*/
2036int partition_info::fix_partition_values(THD *thd,
2037 part_elem_value *val,
2038 partition_element *part_elem)
2039{
2040 part_column_list_val *col_val= val->col_val_array;
2041 DBUG_ENTER("partition_info::fix_partition_values");
2042
2043 if (col_val->fixed)
2044 {
2045 DBUG_RETURN(FALSE);
2046 }
2047
2048 Item *item_expr= col_val->item_expression;
2049 if ((val->null_value= item_expr->null_value))
2050 {
2051 if (part_elem->has_null_value)
2052 {
2053 my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
2054 DBUG_RETURN(TRUE);
2055 }
2056 part_elem->has_null_value= TRUE;
2057 }
2058 else if (item_expr->result_type() != INT_RESULT)
2059 {
2060 my_error(ER_VALUES_IS_NOT_INT_TYPE_ERROR, MYF(0),
2061 part_elem->partition_name);
2062 DBUG_RETURN(TRUE);
2063 }
2064 if (part_type == RANGE_PARTITION)
2065 {
2066 if (part_elem->has_null_value)
2067 {
2068 my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
2069 DBUG_RETURN(TRUE);
2070 }
2071 part_elem->range_value= val->value;
2072 }
2073 col_val->fixed= 2;
2074 DBUG_RETURN(FALSE);
2075}
2076
2077/*
2078 Get column item with a proper character set according to the field
2079
2080 SYNOPSIS
2081 get_column_item()
2082 item Item object to start with
2083 field Field for which the item will be compared to
2084
2085 RETURN VALUES
2086 NULL Error
2087 item Returned item
2088*/
2089
2090Item* partition_info::get_column_item(Item *item, Field *field)
2091{
2092 if (field->result_type() == STRING_RESULT &&
2093 item->collation.collation != field->charset())
2094 {
2095 if (!(item= convert_charset_partition_constant(item,
2096 field->charset())))
2097 {
2098 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2099 return NULL;
2100 }
2101 }
2102 return item;
2103}
2104
2105
2106/*
2107 Evaluate VALUES functions for column list values
2108 SYNOPSIS
2109 fix_column_value_functions()
2110 thd Thread object
2111 col_val List of column values
2112 part_id Partition id we are fixing
2113
2114 RETURN VALUES
2115 TRUE Error
2116 FALSE Success
2117 DESCRIPTION
2118 Fix column VALUES and store in memory array adapted to the data type
2119*/
2120
2121bool partition_info::fix_column_value_functions(THD *thd,
2122 part_elem_value *val,
2123 uint part_id)
2124{
2125 uint n_columns= part_field_list.elements;
2126 bool result= FALSE;
2127 uint i;
2128 part_column_list_val *col_val= val->col_val_array;
2129 DBUG_ENTER("partition_info::fix_column_value_functions");
2130
2131 if (col_val->fixed > 1)
2132 {
2133 DBUG_RETURN(FALSE);
2134 }
2135 for (i= 0; i < n_columns; col_val++, i++)
2136 {
2137 Item *column_item= col_val->item_expression;
2138 Field *field= part_field_array[i];
2139 col_val->part_info= this;
2140 col_val->partition_id= part_id;
2141 if (col_val->max_value)
2142 col_val->column_value= NULL;
2143 else
2144 {
2145 col_val->column_value= NULL;
2146 if (!col_val->null_value)
2147 {
2148 uchar *val_ptr;
2149 uint len= field->pack_length();
2150 sql_mode_t save_sql_mode;
2151 bool save_got_warning;
2152
2153 if (!(column_item= get_column_item(column_item, field)))
2154 {
2155 result= TRUE;
2156 goto end;
2157 }
2158 save_sql_mode= thd->variables.sql_mode;
2159 thd->variables.sql_mode= 0;
2160 save_got_warning= thd->got_warning;
2161 thd->got_warning= 0;
2162 if (column_item->save_in_field(field, TRUE) ||
2163 thd->got_warning)
2164 {
2165 my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
2166 thd->variables.sql_mode= save_sql_mode;
2167 result= TRUE;
2168 goto end;
2169 }
2170 thd->got_warning= save_got_warning;
2171 thd->variables.sql_mode= save_sql_mode;
2172 if (!(val_ptr= (uchar*) thd->memdup(field->ptr, len)))
2173 {
2174 result= TRUE;
2175 goto end;
2176 }
2177 col_val->column_value= val_ptr;
2178 }
2179 }
2180 col_val->fixed= 2;
2181 }
2182end:
2183 DBUG_RETURN(result);
2184}
2185
2186
2187/**
2188 Fix partition data from parser.
2189
2190 @details The parser generates generic data structures, we need to set them
2191 up as the rest of the code expects to find them. This is in reality part
2192 of the syntax check of the parser code.
2193
2194 It is necessary to call this function in the case of a CREATE TABLE
2195 statement, in this case we do it early in the check_partition_info
2196 function.
2197
2198 It is necessary to call this function for ALTER TABLE where we
2199 assign a completely new partition structure, in this case we do it
2200 in prep_alter_part_table after discovering that the partition
2201 structure is entirely redefined.
2202
2203 It's necessary to call this method also for ALTER TABLE ADD/REORGANIZE
2204 of partitions, in this we call it in prep_alter_part_table after
2205 making some initial checks but before going deep to check the partition
2206 info, we also assign the column_list variable before calling this function
2207 here.
2208
2209 Finally we also call it immediately after returning from parsing the
2210 partitioning text found in the frm file.
2211
2212 This function mainly fixes the VALUES parts, these are handled differently
2213 whether or not we use column list partitioning. Since the parser doesn't
2214 know which we are using we need to set-up the old data structures after
2215 the parser is complete when we know if what type of partitioning the
2216 base table is using.
2217
2218 For column lists we will handle this in the fix_column_value_function.
2219 For column lists it is sufficient to verify that the number of columns
2220 and number of elements are in synch with each other. So only partitioning
2221 using functions need to be set-up to their data structures.
2222
2223 @param thd Thread object
2224
2225 @return Operation status
2226 @retval TRUE Failure
2227 @retval FALSE Success
2228*/
2229
2230bool partition_info::fix_parser_data(THD *thd)
2231{
2232 List_iterator<partition_element> it(partitions);
2233 partition_element *part_elem;
2234 uint num_elements;
2235 uint i= 0, j, k;
2236 DBUG_ENTER("partition_info::fix_parser_data");
2237
2238 if (!(part_type == RANGE_PARTITION ||
2239 part_type == LIST_PARTITION))
2240 {
2241 if (part_type == HASH_PARTITION && list_of_part_fields)
2242 {
2243 /* KEY partitioning, check ALGORITHM = N. Should not pass the parser! */
2244 if (key_algorithm > KEY_ALGORITHM_55)
2245 {
2246 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2247 DBUG_RETURN(true);
2248 }
2249 /* If not set, use DEFAULT = 2 for CREATE and ALTER! */
2250 if ((thd_sql_command(thd) == SQLCOM_CREATE_TABLE ||
2251 thd_sql_command(thd) == SQLCOM_ALTER_TABLE) &&
2252 key_algorithm == KEY_ALGORITHM_NONE)
2253 key_algorithm= KEY_ALGORITHM_55;
2254 }
2255 DBUG_RETURN(FALSE);
2256 }
2257 if (is_sub_partitioned() && list_of_subpart_fields)
2258 {
2259 /* KEY subpartitioning, check ALGORITHM = N. Should not pass the parser! */
2260 if (key_algorithm > KEY_ALGORITHM_55)
2261 {
2262 my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2263 DBUG_RETURN(true);
2264 }
2265 /* If not set, use DEFAULT = 2 for CREATE and ALTER! */
2266 if ((thd_sql_command(thd) == SQLCOM_CREATE_TABLE ||
2267 thd_sql_command(thd) == SQLCOM_ALTER_TABLE) &&
2268 key_algorithm == KEY_ALGORITHM_NONE)
2269 key_algorithm= KEY_ALGORITHM_55;
2270 }
2271 defined_max_value= FALSE; // in case it already set (CREATE TABLE LIKE)
2272 do
2273 {
2274 part_elem= it++;
2275 List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
2276 num_elements= part_elem->list_val_list.elements;
2277 if (unlikely(!num_elements && error_if_requires_values()))
2278 DBUG_RETURN(true);
2279 DBUG_ASSERT(part_type == RANGE_PARTITION ?
2280 num_elements == 1U : TRUE);
2281
2282 for (j= 0; j < num_elements; j++)
2283 {
2284 part_elem_value *val= list_val_it++;
2285
2286 if (val->added_items != (column_list ? num_columns : 1))
2287 {
2288 my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
2289 DBUG_RETURN(TRUE);
2290 }
2291
2292 /*
2293 Check the last MAX_VALUE for range partitions and DEFAULT value
2294 for LIST partitions.
2295 Both values are marked with defined_max_value and
2296 default_partition_id.
2297
2298 This is a max_value/default is max_value is set and this is
2299 a normal RANGE (no column list) or if it's a LIST partition:
2300
2301 PARTITION p3 VALUES LESS THAN MAXVALUE
2302 or
2303 PARTITION p3 VALUES DEFAULT
2304 */
2305 if (val->added_items && val->col_val_array[0].max_value &&
2306 (!column_list || part_type == LIST_PARTITION))
2307 {
2308 DBUG_ASSERT(part_type == RANGE_PARTITION ||
2309 part_type == LIST_PARTITION);
2310 if (defined_max_value)
2311 {
2312 my_error((part_type == RANGE_PARTITION) ?
2313 ER_PARTITION_MAXVALUE_ERROR :
2314 ER_PARTITION_DEFAULT_ERROR, MYF(0));
2315 DBUG_RETURN(TRUE);
2316 }
2317
2318 /* For RANGE PARTITION MAX_VALUE must be last */
2319 if (i != (num_parts - 1) &&
2320 part_type != LIST_PARTITION)
2321 {
2322 my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
2323 DBUG_RETURN(TRUE);
2324 }
2325
2326 defined_max_value= TRUE;
2327 default_partition_id= i;
2328 part_elem->max_value= TRUE;
2329 part_elem->range_value= LONGLONG_MAX;
2330 continue;
2331 }
2332
2333 if (column_list)
2334 {
2335 for (k= 0; k < num_columns; k++)
2336 {
2337 part_column_list_val *col_val= &val->col_val_array[k];
2338 if (col_val->null_value && part_type == RANGE_PARTITION)
2339 {
2340 my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
2341 DBUG_RETURN(TRUE);
2342 }
2343 }
2344 }
2345 else
2346 {
2347 if (fix_partition_values(thd, val, part_elem))
2348 DBUG_RETURN(TRUE);
2349 if (val->null_value)
2350 {
2351 /*
2352 Null values aren't required in the value part, they are kept per
2353 partition instance, only LIST partitions have NULL values.
2354 */
2355 list_val_it.remove();
2356 }
2357 }
2358 }
2359 } while (++i < num_parts);
2360 DBUG_RETURN(FALSE);
2361}
2362
2363
2364/**
2365 helper function to compare strings that can also be
2366 a NULL pointer.
2367
2368 @param a char pointer (can be NULL).
2369 @param b char pointer (can be NULL).
2370
2371 @return false if equal
2372 @retval true strings differs
2373 @retval false strings is equal
2374*/
2375
2376static bool strcmp_null(const char *a, const char *b)
2377{
2378 if (!a && !b)
2379 return false;
2380 if (a && b && !strcmp(a, b))
2381 return false;
2382 return true;
2383}
2384
2385
2386/**
2387 Check if the new part_info has the same partitioning.
2388
2389 @param new_part_info New partition definition to compare with.
2390
2391 @return True if not considered to have changed the partitioning.
2392 @retval true Allowed change (only .frm change, compatible distribution).
2393 @retval false Different partitioning, will need redistribution of rows.
2394
2395 @note Currently only used to allow changing from non-set key_algorithm
2396 to a specified key_algorithm, to avoid rebuild when upgrading from 5.1 of
2397 such partitioned tables using numeric colums in the partitioning expression.
2398 For more info see bug#14521864.
2399 Does not check if columns etc has changed, i.e. only for
2400 alter_info->partition_flags == ALTER_PARTITION_INFO.
2401*/
2402
2403bool partition_info::has_same_partitioning(partition_info *new_part_info)
2404{
2405 DBUG_ENTER("partition_info::has_same_partitioning");
2406
2407 DBUG_ASSERT(part_field_array && part_field_array[0]);
2408
2409 /*
2410 Only consider pre 5.5.3 .frm's to have same partitioning as
2411 a new one with KEY ALGORITHM = 1 ().
2412 */
2413
2414 if (part_field_array[0]->table->s->mysql_version >= 50503)
2415 DBUG_RETURN(false);
2416
2417 if (!new_part_info ||
2418 part_type != new_part_info->part_type ||
2419 num_parts != new_part_info->num_parts ||
2420 use_default_partitions != new_part_info->use_default_partitions ||
2421 new_part_info->is_sub_partitioned() != is_sub_partitioned())
2422 DBUG_RETURN(false);
2423
2424 if (part_type != HASH_PARTITION)
2425 {
2426 /*
2427 RANGE or LIST partitioning, check if KEY subpartitioned.
2428 Also COLUMNS partitioning was added in 5.5, so treat that as different.
2429 */
2430 if (!is_sub_partitioned() ||
2431 !new_part_info->is_sub_partitioned() ||
2432 column_list ||
2433 new_part_info->column_list ||
2434 !list_of_subpart_fields ||
2435 !new_part_info->list_of_subpart_fields ||
2436 new_part_info->num_subparts != num_subparts ||
2437 new_part_info->subpart_field_list.elements !=
2438 subpart_field_list.elements ||
2439 new_part_info->use_default_subpartitions !=
2440 use_default_subpartitions)
2441 DBUG_RETURN(false);
2442 }
2443 else
2444 {
2445 /* Check if KEY partitioned. */
2446 if (!new_part_info->list_of_part_fields ||
2447 !list_of_part_fields ||
2448 new_part_info->part_field_list.elements != part_field_list.elements)
2449 DBUG_RETURN(false);
2450 }
2451
2452 /* Check that it will use the same fields in KEY (fields) list. */
2453 List_iterator<const char> old_field_name_it(part_field_list);
2454 List_iterator<const char> new_field_name_it(new_part_info->part_field_list);
2455 const char *old_name, *new_name;
2456 while ((old_name= old_field_name_it++))
2457 {
2458 new_name= new_field_name_it++;
2459 if (!new_name || my_strcasecmp(system_charset_info,
2460 new_name,
2461 old_name))
2462 DBUG_RETURN(false);
2463 }
2464
2465 if (is_sub_partitioned())
2466 {
2467 /* Check that it will use the same fields in KEY subpart fields list. */
2468 List_iterator<const char> old_field_name_it(subpart_field_list);
2469 List_iterator<const char> new_field_name_it(new_part_info->subpart_field_list);
2470 const char *old_name, *new_name;
2471 while ((old_name= old_field_name_it++))
2472 {
2473 new_name= new_field_name_it++;
2474 if (!new_name || my_strcasecmp(system_charset_info,
2475 new_name,
2476 old_name))
2477 DBUG_RETURN(false);
2478 }
2479 }
2480
2481 if (!use_default_partitions)
2482 {
2483 /*
2484 Loop over partitions/subpartition to verify that they are
2485 the same, including state and name.
2486 */
2487 List_iterator<partition_element> part_it(partitions);
2488 List_iterator<partition_element> new_part_it(new_part_info->partitions);
2489 uint i= 0;
2490 do
2491 {
2492 partition_element *part_elem= part_it++;
2493 partition_element *new_part_elem= new_part_it++;
2494 /*
2495 The following must match:
2496 partition_name, tablespace_name, data_file_name, index_file_name,
2497 engine_type, part_max_rows, part_min_rows, nodegroup_id.
2498 (max_value, signed_flag, has_null_value only on partition level,
2499 RANGE/LIST)
2500 The following can differ:
2501 - part_comment
2502 part_state must be PART_NORMAL!
2503 */
2504 if (!part_elem || !new_part_elem ||
2505 strcmp(part_elem->partition_name,
2506 new_part_elem->partition_name) ||
2507 part_elem->part_state != PART_NORMAL ||
2508 new_part_elem->part_state != PART_NORMAL ||
2509 part_elem->max_value != new_part_elem->max_value ||
2510 part_elem->signed_flag != new_part_elem->signed_flag ||
2511 part_elem->has_null_value != new_part_elem->has_null_value)
2512 DBUG_RETURN(false);
2513
2514 /* new_part_elem may not have engine_type set! */
2515 if (new_part_elem->engine_type &&
2516 part_elem->engine_type != new_part_elem->engine_type)
2517 DBUG_RETURN(false);
2518
2519 if (is_sub_partitioned())
2520 {
2521 /*
2522 Check that both old and new partition has the same definition
2523 (VALUES IN/VALUES LESS THAN) (No COLUMNS partitioning, see above)
2524 */
2525 if (part_type == LIST_PARTITION)
2526 {
2527 List_iterator<part_elem_value> list_vals(part_elem->list_val_list);
2528 List_iterator<part_elem_value>
2529 new_list_vals(new_part_elem->list_val_list);
2530 part_elem_value *val;
2531 part_elem_value *new_val;
2532 while ((val= list_vals++))
2533 {
2534 new_val= new_list_vals++;
2535 if (!new_val)
2536 DBUG_RETURN(false);
2537 if ((!val->null_value && !new_val->null_value) &&
2538 val->value != new_val->value)
2539 DBUG_RETURN(false);
2540 }
2541 if (new_list_vals++)
2542 DBUG_RETURN(false);
2543 }
2544 else
2545 {
2546 DBUG_ASSERT(part_type == RANGE_PARTITION);
2547 if (new_part_elem->range_value != part_elem->range_value)
2548 DBUG_RETURN(false);
2549 }
2550
2551 if (!use_default_subpartitions)
2552 {
2553 List_iterator<partition_element>
2554 sub_part_it(part_elem->subpartitions);
2555 List_iterator<partition_element>
2556 new_sub_part_it(new_part_elem->subpartitions);
2557 uint j= 0;
2558 do
2559 {
2560 partition_element *sub_part_elem= sub_part_it++;
2561 partition_element *new_sub_part_elem= new_sub_part_it++;
2562 /* new_part_elem may not have engine_type set! */
2563 if (new_sub_part_elem->engine_type &&
2564 sub_part_elem->engine_type != new_sub_part_elem->engine_type)
2565 DBUG_RETURN(false);
2566
2567 if (strcmp(sub_part_elem->partition_name,
2568 new_sub_part_elem->partition_name) ||
2569 sub_part_elem->part_state != PART_NORMAL ||
2570 new_sub_part_elem->part_state != PART_NORMAL ||
2571 sub_part_elem->part_min_rows !=
2572 new_sub_part_elem->part_min_rows ||
2573 sub_part_elem->part_max_rows !=
2574 new_sub_part_elem->part_max_rows ||
2575 sub_part_elem->nodegroup_id !=
2576 new_sub_part_elem->nodegroup_id)
2577 DBUG_RETURN(false);
2578
2579 if (strcmp_null(sub_part_elem->data_file_name,
2580 new_sub_part_elem->data_file_name) ||
2581 strcmp_null(sub_part_elem->index_file_name,
2582 new_sub_part_elem->index_file_name) ||
2583 strcmp_null(sub_part_elem->tablespace_name,
2584 new_sub_part_elem->tablespace_name))
2585 DBUG_RETURN(false);
2586
2587 } while (++j < num_subparts);
2588 }
2589 }
2590 else
2591 {
2592 if (part_elem->part_min_rows != new_part_elem->part_min_rows ||
2593 part_elem->part_max_rows != new_part_elem->part_max_rows ||
2594 part_elem->nodegroup_id != new_part_elem->nodegroup_id)
2595 DBUG_RETURN(false);
2596
2597 if (strcmp_null(part_elem->data_file_name,
2598 new_part_elem->data_file_name) ||
2599 strcmp_null(part_elem->index_file_name,
2600 new_part_elem->index_file_name) ||
2601 strcmp_null(part_elem->tablespace_name,
2602 new_part_elem->tablespace_name))
2603 DBUG_RETURN(false);
2604 }
2605 } while (++i < num_parts);
2606 }
2607
2608 /*
2609 Only if key_algorithm was not specified before and it is now set,
2610 consider this as nothing was changed, and allow change without rebuild!
2611 */
2612 if (key_algorithm != partition_info::KEY_ALGORITHM_NONE ||
2613 new_part_info->key_algorithm == partition_info::KEY_ALGORITHM_NONE)
2614 DBUG_RETURN(false);
2615
2616 DBUG_RETURN(true);
2617}
2618
2619
2620void partition_info::print_debug(const char *str, uint *value)
2621{
2622 DBUG_ENTER("print_debug");
2623 if (value)
2624 DBUG_PRINT("info", ("parser: %s, val = %u", str, *value));
2625 else
2626 DBUG_PRINT("info", ("parser: %s", str));
2627 DBUG_VOID_RETURN;
2628}
2629#else /* WITH_PARTITION_STORAGE_ENGINE */
2630 /*
2631 For builds without partitioning we need to define these functions
2632 since we they are called from the parser. The parser cannot
2633 remove code parts using ifdef, but the code parts cannot be called
2634 so we simply need to add empty functions to make the linker happy.
2635 */
2636part_column_list_val *partition_info::add_column_value(THD *thd)
2637{
2638 return NULL;
2639}
2640
2641bool partition_info::set_part_expr(THD *thd, char *start_token, Item *item_ptr,
2642 char *end_token, bool is_subpart)
2643{
2644 (void)start_token;
2645 (void)item_ptr;
2646 (void)end_token;
2647 (void)is_subpart;
2648 return FALSE;
2649}
2650
2651int partition_info::reorganize_into_single_field_col_val(THD *thd)
2652{
2653 return 0;
2654}
2655
2656bool partition_info::init_column_part(THD *thd)
2657{
2658 return FALSE;
2659}
2660
2661bool partition_info::add_column_list_value(THD *thd, Item *item)
2662{
2663 return FALSE;
2664}
2665int partition_info::add_max_value(THD *thd)
2666{
2667 return 0;
2668}
2669
2670void partition_info::print_debug(const char *str, uint *value)
2671{
2672}
2673
2674bool check_partition_dirs(partition_info *part_info)
2675{
2676 return 0;
2677}
2678
2679#endif /* WITH_PARTITION_STORAGE_ENGINE */
2680
2681bool partition_info::vers_init_info(THD * thd)
2682{
2683 part_type= VERSIONING_PARTITION;
2684 list_of_part_fields= TRUE;
2685 column_list= TRUE;
2686 num_columns= 1;
2687 vers_info= new (thd->mem_root) Vers_part_info;
2688 if (unlikely(!vers_info))
2689 return true;
2690
2691 return false;
2692}
2693
2694
2695bool partition_info::error_if_requires_values() const
2696{
2697 switch (part_type) {
2698 case NOT_A_PARTITION:
2699 case HASH_PARTITION:
2700 case VERSIONING_PARTITION:
2701 break;
2702 case RANGE_PARTITION:
2703 my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
2704 return true;
2705 case LIST_PARTITION:
2706 my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN");
2707 return true;
2708 }
2709 return false;
2710}
2711