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