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