MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_partition.cc
1 /* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /*
17  This file is a container for general functionality related
18  to partitioning introduced in MySQL version 5.1. It contains functionality
19  used by all handlers that support partitioning, such as
20  the partitioning handler itself and the NDB handler.
21  (Much of the code in this file has been split into partition_info.cc and
22  the header files partition_info.h + partition_element.h + sql_partition.h)
23 
24  The first version was written by Mikael Ronstrom 2004-2006.
25  Various parts of the optimizer code was written by Sergey Petrunia.
26  Code have been maintained by Mattias Jonsson.
27  The second version was written by Mikael Ronstrom 2006-2007 with some
28  final fixes for partition pruning in 2008-2009 with assistance from Sergey
29  Petrunia and Mattias Jonsson.
30 
31  The first version supports RANGE partitioning, LIST partitioning, HASH
32  partitioning and composite partitioning (hereafter called subpartitioning)
33  where each RANGE/LIST partitioning is HASH partitioned. The hash function
34  can either be supplied by the user or by only a list of fields (also
35  called KEY partitioning), where the MySQL server will use an internal
36  hash function.
37  There are quite a few defaults that can be used as well.
38 
39  The second version introduces a new variant of RANGE and LIST partitioning
40  which is often referred to as column lists in the code variables. This
41  enables a user to specify a set of columns and their concatenated value
42  as the partition value. By comparing the concatenation of these values
43  the proper partition can be choosen.
44 */
45 
46 /* Some general useful functions */
47 
48 #define MYSQL_LEX 1
49 #include "sql_priv.h"
50 #include "unireg.h" // REQUIRED: for other includes
51 #include "sql_partition.h"
52 #include "key.h" // key_restore
53 #include "sql_parse.h" // parse_sql
54 #include "sql_cache.h" // query_cache_invalidate3
55 #include "lock.h" // mysql_lock_remove
56 #include "sql_show.h" // append_identifier
57 #include <errno.h>
58 #include <m_ctype.h>
59 #include "my_md5.h"
60 #include "transaction.h"
61 #include "debug_sync.h"
62 
63 #include "sql_base.h" // close_all_tables_for_name
64 #include "sql_table.h" // build_table_filename,
65  // build_table_shadow_filename,
66  // table_to_filename
67  // mysql_*_alter_copy_data
68 #include "opt_range.h" // store_key_image_to_rec
69 #include "sql_analyse.h" // append_escaped
70 #include "sql_alter.h" // Alter_table_ctx
71 
72 #include <algorithm>
73 using std::max;
74 using std::min;
75 
76 #ifdef WITH_PARTITION_STORAGE_ENGINE
77 #include "ha_partition.h"
78 
79 #define ERROR_INJECT_CRASH(code) \
80  DBUG_EVALUATE_IF(code, (DBUG_SUICIDE(), 0), 0)
81 #define ERROR_INJECT_ERROR(code) \
82  DBUG_EVALUATE_IF(code, (my_error(ER_UNKNOWN_ERROR, MYF(0)), TRUE), 0)
83 
84 /*
85  Partition related functions declarations and some static constants;
86 */
87 const LEX_STRING partition_keywords[]=
88 {
89  { C_STRING_WITH_LEN("HASH") },
90  { C_STRING_WITH_LEN("RANGE") },
91  { C_STRING_WITH_LEN("LIST") },
92  { C_STRING_WITH_LEN("KEY") },
93  { C_STRING_WITH_LEN("MAXVALUE") },
94  { C_STRING_WITH_LEN("LINEAR ") },
95  { C_STRING_WITH_LEN(" COLUMNS") },
96  { C_STRING_WITH_LEN("ALGORITHM") }
97 
98 };
99 static const char *part_str= "PARTITION";
100 static const char *sub_str= "SUB";
101 static const char *by_str= "BY";
102 static const char *space_str= " ";
103 static const char *equal_str= "=";
104 static const char *end_paren_str= ")";
105 static const char *begin_paren_str= "(";
106 static const char *comma_str= ",";
107 
108 int get_partition_id_list_col(partition_info *part_info,
109  uint32 *part_id,
110  longlong *func_value);
111 int get_partition_id_list(partition_info *part_info,
112  uint32 *part_id,
113  longlong *func_value);
114 int get_partition_id_range_col(partition_info *part_info,
115  uint32 *part_id,
116  longlong *func_value);
117 int get_partition_id_range(partition_info *part_info,
118  uint32 *part_id,
119  longlong *func_value);
120 static int get_part_id_charset_func_part(partition_info *part_info,
121  uint32 *part_id,
122  longlong *func_value);
123 static int get_part_id_charset_func_subpart(partition_info *part_info,
124  uint32 *part_id);
125 int get_partition_id_hash_nosub(partition_info *part_info,
126  uint32 *part_id,
127  longlong *func_value);
128 int get_partition_id_key_nosub(partition_info *part_info,
129  uint32 *part_id,
130  longlong *func_value);
131 int get_partition_id_linear_hash_nosub(partition_info *part_info,
132  uint32 *part_id,
133  longlong *func_value);
134 int get_partition_id_linear_key_nosub(partition_info *part_info,
135  uint32 *part_id,
136  longlong *func_value);
137 int get_partition_id_with_sub(partition_info *part_info,
138  uint32 *part_id,
139  longlong *func_value);
140 int get_partition_id_hash_sub(partition_info *part_info,
141  uint32 *part_id);
142 int get_partition_id_key_sub(partition_info *part_info,
143  uint32 *part_id);
144 int get_partition_id_linear_hash_sub(partition_info *part_info,
145  uint32 *part_id);
146 int get_partition_id_linear_key_sub(partition_info *part_info,
147  uint32 *part_id);
148 static uint32 get_next_partition_via_walking(PARTITION_ITERATOR*);
149 static void set_up_range_analysis_info(partition_info *part_info);
150 static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR*);
151 #endif
152 
153 uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter);
154 uint32 get_next_partition_id_list(PARTITION_ITERATOR* part_iter);
155 int get_part_iter_for_interval_via_mapping(partition_info *part_info,
156  bool is_subpart,
157  uint32 *store_length_array,
158  uchar *min_value, uchar *max_value,
159  uint min_len, uint max_len,
160  uint flags,
161  PARTITION_ITERATOR *part_iter);
162 int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
163  bool is_subpart,
164  uint32 *store_length_array,
165  uchar *min_value, uchar *max_value,
166  uint min_len, uint max_len,
167  uint flags,
168  PARTITION_ITERATOR *part_iter);
169 int get_part_iter_for_interval_via_walking(partition_info *part_info,
170  bool is_subpart,
171  uint32 *store_length_array,
172  uchar *min_value, uchar *max_value,
173  uint min_len, uint max_len,
174  uint flags,
175  PARTITION_ITERATOR *part_iter);
176 
177 #ifdef WITH_PARTITION_STORAGE_ENGINE
178 static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec);
179 static int cmp_rec_and_tuple_prune(part_column_list_val *val,
180  uint32 n_vals_in_rec,
181  bool is_left_endpoint,
182  bool include_endpoint);
183 
184 /*
185  Convert constants in VALUES definition to the character set the
186  corresponding field uses.
187 
188  SYNOPSIS
189  convert_charset_partition_constant()
190  item Item to convert
191  cs Character set to convert to
192 
193  RETURN VALUE
194  NULL Error
195  item New converted item
196 */
197 
198 Item* convert_charset_partition_constant(Item *item, const CHARSET_INFO *cs)
199 {
200  THD *thd= current_thd;
201  Name_resolution_context *context= &thd->lex->current_select->context;
202  TABLE_LIST *save_list= context->table_list;
203  const char *save_where= thd->where;
204 
205  item= item->safe_charset_converter(cs);
206  context->table_list= NULL;
207  thd->where= "convert character set partition constant";
208  if (!item || item->fix_fields(thd, (Item**)NULL))
209  item= NULL;
210  thd->where= save_where;
211  context->table_list= save_list;
212  return item;
213 }
214 
215 
227 static bool is_name_in_list(char *name, List<char> list_names)
228 {
229  List_iterator<char> names_it(list_names);
230  uint num_names= list_names.elements;
231  uint i= 0;
232 
233  do
234  {
235  char *list_name= names_it++;
236  if (!(my_strcasecmp(system_charset_info, name, list_name)))
237  return TRUE;
238  } while (++i < num_names);
239  return FALSE;
240 }
241 
242 
243 
244 /*
245  Set-up defaults for partitions.
246 
247  SYNOPSIS
248  partition_default_handling()
249  table Table object
250  part_info Partition info to set up
251  is_create_table_ind Is this part of a table creation
252  normalized_path Normalized path name of table and database
253 
254  RETURN VALUES
255  TRUE Error
256  FALSE Success
257 */
258 
259 bool partition_default_handling(TABLE *table, partition_info *part_info,
260  bool is_create_table_ind,
261  const char *normalized_path)
262 {
263  DBUG_ENTER("partition_default_handling");
264 
265  if (!is_create_table_ind)
266  {
267  if (part_info->use_default_num_partitions)
268  {
269  if (table->file->get_no_parts(normalized_path, &part_info->num_parts))
270  {
271  DBUG_RETURN(TRUE);
272  }
273  }
274  else if (part_info->is_sub_partitioned() &&
275  part_info->use_default_num_subpartitions)
276  {
277  uint num_parts;
278  if (table->file->get_no_parts(normalized_path, &num_parts))
279  {
280  DBUG_RETURN(TRUE);
281  }
282  DBUG_ASSERT(part_info->num_parts > 0);
283  DBUG_ASSERT((num_parts % part_info->num_parts) == 0);
284  part_info->num_subparts= num_parts / part_info->num_parts;
285  }
286  }
287  part_info->set_up_defaults_for_partitioning(table->file,
288  NULL, 0U);
289  DBUG_RETURN(FALSE);
290 }
291 
292 
293 /*
294  A useful routine used by update_row for partition handlers to calculate
295  the partition ids of the old and the new record.
296 
297  SYNOPSIS
298  get_part_for_update()
299  old_data Buffer of old record
300  new_data Buffer of new record
301  rec0 Reference to table->record[0]
302  part_info Reference to partition information
303  out:old_part_id The returned partition id of old record
304  out:new_part_id The returned partition id of new record
305 
306  RETURN VALUE
307  0 Success
308  > 0 Error code
309 */
310 
311 int get_parts_for_update(const uchar *old_data, uchar *new_data,
312  const uchar *rec0, partition_info *part_info,
313  uint32 *old_part_id, uint32 *new_part_id,
314  longlong *new_func_value)
315 {
316  Field **part_field_array= part_info->full_part_field_array;
317  int error;
318  longlong old_func_value;
319  DBUG_ENTER("get_parts_for_update");
320 
321  DBUG_ASSERT(new_data == rec0); // table->record[0]
322  set_field_ptr(part_field_array, old_data, rec0);
323  error= part_info->get_partition_id(part_info, old_part_id,
324  &old_func_value);
325  set_field_ptr(part_field_array, rec0, old_data);
326  if (unlikely(error)) // Should never happen
327  {
328  DBUG_ASSERT(0);
329  DBUG_RETURN(error);
330  }
331 #ifdef NOT_NEEDED
332  if (new_data == rec0)
333 #endif
334  {
335  if (unlikely(error= part_info->get_partition_id(part_info,
336  new_part_id,
337  new_func_value)))
338  {
339  DBUG_RETURN(error);
340  }
341  }
342 #ifdef NOT_NEEDED
343  else
344  {
345  /*
346  This branch should never execute but it is written anyways for
347  future use. It will be tested by ensuring that the above
348  condition is false in one test situation before pushing the code.
349  */
350  set_field_ptr(part_field_array, new_data, rec0);
351  error= part_info->get_partition_id(part_info, new_part_id,
352  new_func_value);
353  set_field_ptr(part_field_array, rec0, new_data);
354  if (unlikely(error))
355  {
356  DBUG_RETURN(error);
357  }
358  }
359 #endif
360  DBUG_RETURN(0);
361 }
362 
363 
364 /*
365  A useful routine used by delete_row for partition handlers to calculate
366  the partition id.
367 
368  SYNOPSIS
369  get_part_for_delete()
370  buf Buffer of old record
371  rec0 Reference to table->record[0]
372  part_info Reference to partition information
373  out:part_id The returned partition id to delete from
374 
375  RETURN VALUE
376  0 Success
377  > 0 Error code
378 
379  DESCRIPTION
380  Dependent on whether buf is not record[0] we need to prepare the
381  fields. Then we call the function pointer get_partition_id to
382  calculate the partition id.
383 */
384 
385 int get_part_for_delete(const uchar *buf, const uchar *rec0,
386  partition_info *part_info, uint32 *part_id)
387 {
388  int error;
389  longlong func_value;
390  DBUG_ENTER("get_part_for_delete");
391 
392  if (likely(buf == rec0))
393  {
394  if (unlikely((error= part_info->get_partition_id(part_info, part_id,
395  &func_value))))
396  {
397  DBUG_RETURN(error);
398  }
399  DBUG_PRINT("info", ("Delete from partition %d", *part_id));
400  }
401  else
402  {
403  Field **part_field_array= part_info->full_part_field_array;
404  set_field_ptr(part_field_array, buf, rec0);
405  error= part_info->get_partition_id(part_info, part_id, &func_value);
406  set_field_ptr(part_field_array, rec0, buf);
407  if (unlikely(error))
408  {
409  DBUG_RETURN(error);
410  }
411  DBUG_PRINT("info", ("Delete from partition %d (path2)", *part_id));
412  }
413  DBUG_RETURN(0);
414 }
415 
416 
417 /*
418  This method is used to set-up both partition and subpartitioning
419  field array and used for all types of partitioning.
420  It is part of the logic around fix_partition_func.
421 
422  SYNOPSIS
423  set_up_field_array()
424  table TABLE object for which partition fields are set-up
425  sub_part Is the table subpartitioned as well
426 
427  RETURN VALUE
428  TRUE Error, some field didn't meet requirements
429  FALSE Ok, partition field array set-up
430 
431  DESCRIPTION
432 
433  A great number of functions below here is part of the fix_partition_func
434  method. It is used to set up the partition structures for execution from
435  openfrm. It is called at the end of the openfrm when the table struct has
436  been set-up apart from the partition information.
437  It involves:
438  1) Setting arrays of fields for the partition functions.
439  2) Setting up binary search array for LIST partitioning
440  3) Setting up array for binary search for RANGE partitioning
441  4) Setting up key_map's to assist in quick evaluation whether one
442  can deduce anything from a given index of what partition to use
443  5) Checking whether a set of partitions can be derived from a range on
444  a field in the partition function.
445  As part of doing this there is also a great number of error controls.
446  This is actually the place where most of the things are checked for
447  partition information when creating a table.
448  Things that are checked includes
449  1) All fields of partition function in Primary keys and unique indexes
450  (if not supported)
451 
452 
453  Create an array of partition fields (NULL terminated). Before this method
454  is called fix_fields or find_table_in_sef has been called to set
455  GET_FIXED_FIELDS_FLAG on all fields that are part of the partition
456  function.
457 */
458 
459 static bool set_up_field_array(TABLE *table,
460  bool is_sub_part)
461 {
462  Field **ptr, *field, **field_array;
463  uint num_fields= 0;
464  uint size_field_array;
465  uint i= 0;
466  uint inx;
467  partition_info *part_info= table->part_info;
468  int result= FALSE;
469  DBUG_ENTER("set_up_field_array");
470 
471  ptr= table->field;
472  while ((field= *(ptr++)))
473  {
474  if (field->flags & GET_FIXED_FIELDS_FLAG)
475  num_fields++;
476  }
477  if (num_fields > MAX_REF_PARTS)
478  {
479  char *err_str;
480  if (is_sub_part)
481  err_str= (char*)"subpartition function";
482  else
483  err_str= (char*)"partition function";
484  my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0), err_str);
485  DBUG_RETURN(TRUE);
486  }
487  if (num_fields == 0)
488  {
489  /*
490  We are using hidden key as partitioning field
491  */
492  DBUG_ASSERT(!is_sub_part);
493  DBUG_RETURN(result);
494  }
495  size_field_array= (num_fields+1)*sizeof(Field*);
496  field_array= (Field**)sql_calloc(size_field_array);
497  if (unlikely(!field_array))
498  {
499  mem_alloc_error(size_field_array);
500  result= TRUE;
501  }
502  ptr= table->field;
503  while ((field= *(ptr++)))
504  {
505  if (field->flags & GET_FIXED_FIELDS_FLAG)
506  {
507  field->flags&= ~GET_FIXED_FIELDS_FLAG;
508  field->flags|= FIELD_IN_PART_FUNC_FLAG;
509  if (likely(!result))
510  {
511  if (!is_sub_part && part_info->column_list)
512  {
513  List_iterator<char> it(part_info->part_field_list);
514  char *field_name;
515 
516  DBUG_ASSERT(num_fields == part_info->part_field_list.elements);
517  inx= 0;
518  do
519  {
520  field_name= it++;
521  if (!my_strcasecmp(system_charset_info,
522  field_name,
523  field->field_name))
524  break;
525  } while (++inx < num_fields);
526  if (inx == num_fields)
527  {
528  /*
529  Should not occur since it should already been checked in either
530  add_column_list_values, handle_list_of_fields,
531  check_partition_info etc.
532  */
533  DBUG_ASSERT(0);
534  my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
535  result= TRUE;
536  continue;
537  }
538  }
539  else
540  inx= i;
541  field_array[inx]= field;
542  i++;
543 
544  /*
545  We check that the fields are proper. It is required for each
546  field in a partition function to:
547  1) Not be a BLOB of any type
548  A BLOB takes too long time to evaluate so we don't want it for
549  performance reasons.
550  */
551 
552  if (unlikely(field->flags & BLOB_FLAG))
553  {
554  my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0));
555  result= TRUE;
556  }
557  }
558  }
559  }
560  field_array[num_fields]= 0;
561  if (!is_sub_part)
562  {
563  part_info->part_field_array= field_array;
564  part_info->num_part_fields= num_fields;
565  }
566  else
567  {
568  part_info->subpart_field_array= field_array;
569  part_info->num_subpart_fields= num_fields;
570  }
571  DBUG_RETURN(result);
572 }
573 
574 
575 
576 /*
577  Create a field array including all fields of both the partitioning and the
578  subpartitioning functions.
579 
580  SYNOPSIS
581  create_full_part_field_array()
582  thd Thread handle
583  table TABLE object for which partition fields are set-up
584  part_info Reference to partitioning data structure
585 
586  RETURN VALUE
587  TRUE Memory allocation of field array failed
588  FALSE Ok
589 
590  DESCRIPTION
591  If there is no subpartitioning then the same array is used as for the
592  partitioning. Otherwise a new array is built up using the flag
593  FIELD_IN_PART_FUNC in the field object.
594  This function is called from fix_partition_func
595 */
596 
597 static bool create_full_part_field_array(THD *thd, TABLE *table,
598  partition_info *part_info)
599 {
600  bool result= FALSE;
601  Field **ptr;
602  my_bitmap_map *bitmap_buf;
603  DBUG_ENTER("create_full_part_field_array");
604 
605  if (!part_info->is_sub_partitioned())
606  {
607  part_info->full_part_field_array= part_info->part_field_array;
608  part_info->num_full_part_fields= part_info->num_part_fields;
609  }
610  else
611  {
612  Field *field, **field_array;
613  uint num_part_fields=0, size_field_array;
614  ptr= table->field;
615  while ((field= *(ptr++)))
616  {
617  if (field->flags & FIELD_IN_PART_FUNC_FLAG)
618  num_part_fields++;
619  }
620  size_field_array= (num_part_fields+1)*sizeof(Field*);
621  field_array= (Field**)sql_calloc(size_field_array);
622  if (unlikely(!field_array))
623  {
624  mem_alloc_error(size_field_array);
625  result= TRUE;
626  goto end;
627  }
628  num_part_fields= 0;
629  ptr= table->field;
630  while ((field= *(ptr++)))
631  {
632  if (field->flags & FIELD_IN_PART_FUNC_FLAG)
633  field_array[num_part_fields++]= field;
634  }
635  field_array[num_part_fields]=0;
636  part_info->full_part_field_array= field_array;
637  part_info->num_full_part_fields= num_part_fields;
638  }
639 
640  /*
641  Initialize the set of all fields used in partition and subpartition
642  expression. Required for testing of partition fields in write_set
643  when updating. We need to set all bits in read_set because the row
644  may need to be inserted in a different [sub]partition.
645  */
646  if (!(bitmap_buf= (my_bitmap_map*)
647  thd->alloc(bitmap_buffer_size(table->s->fields))))
648  {
649  mem_alloc_error(bitmap_buffer_size(table->s->fields));
650  result= TRUE;
651  goto end;
652  }
653  if (bitmap_init(&part_info->full_part_field_set, bitmap_buf,
654  table->s->fields, FALSE))
655  {
656  mem_alloc_error(table->s->fields);
657  result= TRUE;
658  goto end;
659  }
660  /*
661  full_part_field_array may be NULL if storage engine supports native
662  partitioning.
663  */
664  if ((ptr= part_info->full_part_field_array))
665  for (; *ptr; ptr++)
666  bitmap_set_bit(&part_info->full_part_field_set, (*ptr)->field_index);
667 
668 end:
669  DBUG_RETURN(result);
670 }
671 
672 
673 /*
674 
675  Clear flag GET_FIXED_FIELDS_FLAG in all fields of a key previously set by
676  set_indicator_in_key_fields (always used in pairs).
677 
678  SYNOPSIS
679  clear_indicator_in_key_fields()
680  key_info Reference to find the key fields
681 
682  RETURN VALUE
683  NONE
684 
685  DESCRIPTION
686  These support routines is used to set/reset an indicator of all fields
687  in a certain key. It is used in conjunction with another support routine
688  that traverse all fields in the PF to find if all or some fields in the
689  PF is part of the key. This is used to check primary keys and unique
690  keys involve all fields in PF (unless supported) and to derive the
691  key_map's used to quickly decide whether the index can be used to
692  derive which partitions are needed to scan.
693 */
694 
695 static void clear_indicator_in_key_fields(KEY *key_info)
696 {
697  KEY_PART_INFO *key_part;
698  uint key_parts= key_info->user_defined_key_parts, i;
699  for (i= 0, key_part=key_info->key_part; i < key_parts; i++, key_part++)
700  key_part->field->flags&= (~GET_FIXED_FIELDS_FLAG);
701 }
702 
703 
704 /*
705  Set flag GET_FIXED_FIELDS_FLAG in all fields of a key.
706 
707  SYNOPSIS
708  set_indicator_in_key_fields
709  key_info Reference to find the key fields
710 
711  RETURN VALUE
712  NONE
713 */
714 
715 static void set_indicator_in_key_fields(KEY *key_info)
716 {
717  KEY_PART_INFO *key_part;
718  uint key_parts= key_info->user_defined_key_parts, i;
719  for (i= 0, key_part=key_info->key_part; i < key_parts; i++, key_part++)
720  key_part->field->flags|= GET_FIXED_FIELDS_FLAG;
721 }
722 
723 
724 /*
725  Check if all or some fields in partition field array is part of a key
726  previously used to tag key fields.
727 
728  SYNOPSIS
729  check_fields_in_PF()
730  ptr Partition field array
731  out:all_fields Is all fields of partition field array used in key
732  out:some_fields Is some fields of partition field array used in key
733 
734  RETURN VALUE
735  all_fields, some_fields
736 */
737 
738 static void check_fields_in_PF(Field **ptr, bool *all_fields,
739  bool *some_fields)
740 {
741  DBUG_ENTER("check_fields_in_PF");
742 
743  *all_fields= TRUE;
744  *some_fields= FALSE;
745  if ((!ptr) || !(*ptr))
746  {
747  *all_fields= FALSE;
748  DBUG_VOID_RETURN;
749  }
750  do
751  {
752  /* Check if the field of the PF is part of the current key investigated */
753  if ((*ptr)->flags & GET_FIXED_FIELDS_FLAG)
754  *some_fields= TRUE;
755  else
756  *all_fields= FALSE;
757  } while (*(++ptr));
758  DBUG_VOID_RETURN;
759 }
760 
761 
762 /*
763  Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
764  This routine is used for error handling purposes.
765 
766  SYNOPSIS
767  clear_field_flag()
768  table TABLE object for which partition fields are set-up
769 
770  RETURN VALUE
771  NONE
772 */
773 
774 static void clear_field_flag(TABLE *table)
775 {
776  Field **ptr;
777  DBUG_ENTER("clear_field_flag");
778 
779  for (ptr= table->field; *ptr; ptr++)
780  (*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
781  DBUG_VOID_RETURN;
782 }
783 
784 
785 /*
786  find_field_in_table_sef finds the field given its name. All fields get
787  GET_FIXED_FIELDS_FLAG set.
788 
789  SYNOPSIS
790  handle_list_of_fields()
791  it A list of field names for the partition function
792  table TABLE object for which partition fields are set-up
793  part_info Reference to partitioning data structure
794  sub_part Is the table subpartitioned as well
795 
796  RETURN VALUE
797  TRUE Fields in list of fields not part of table
798  FALSE All fields ok and array created
799 
800  DESCRIPTION
801  This routine sets-up the partition field array for KEY partitioning, it
802  also verifies that all fields in the list of fields is actually a part of
803  the table.
804 
805 */
806 
807 
808 static bool handle_list_of_fields(List_iterator<char> it,
809  TABLE *table,
810  partition_info *part_info,
811  bool is_sub_part)
812 {
813  Field *field;
814  bool result;
815  char *field_name;
816  bool is_list_empty= TRUE;
817  DBUG_ENTER("handle_list_of_fields");
818 
819  while ((field_name= it++))
820  {
821  is_list_empty= FALSE;
822  field= find_field_in_table_sef(table, field_name);
823  if (likely(field != 0))
824  field->flags|= GET_FIXED_FIELDS_FLAG;
825  else
826  {
827  my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
828  clear_field_flag(table);
829  result= TRUE;
830  goto end;
831  }
832  }
833  if (is_list_empty && part_info->part_type == HASH_PARTITION)
834  {
835  uint primary_key= table->s->primary_key;
836  if (primary_key != MAX_KEY)
837  {
838  uint num_key_parts= table->key_info[primary_key].user_defined_key_parts, i;
839  /*
840  In the case of an empty list we use primary key as partition key.
841  */
842  for (i= 0; i < num_key_parts; i++)
843  {
844  Field *field= table->key_info[primary_key].key_part[i].field;
845  field->flags|= GET_FIXED_FIELDS_FLAG;
846  }
847  }
848  else
849  {
850  if (table->s->db_type()->partition_flags &&
851  (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) &&
852  (table->s->db_type()->partition_flags() & HA_CAN_PARTITION))
853  {
854  /*
855  This engine can handle automatic partitioning and there is no
856  primary key. In this case we rely on that the engine handles
857  partitioning based on a hidden key. Thus we allocate no
858  array for partitioning fields.
859  */
860  DBUG_RETURN(FALSE);
861  }
862  else
863  {
864  my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
865  DBUG_RETURN(TRUE);
866  }
867  }
868  }
869  result= set_up_field_array(table, is_sub_part);
870 end:
871  DBUG_RETURN(result);
872 }
873 
874 
875 /*
876  Support function to check if all VALUES * (expression) is of the
877  right sign (no signed constants when unsigned partition function)
878 
879  SYNOPSIS
880  check_signed_flag()
881  part_info Partition info object
882 
883  RETURN VALUES
884  0 No errors due to sign errors
885  >0 Sign error
886 */
887 
888 int check_signed_flag(partition_info *part_info)
889 {
890  int error= 0;
891  uint i= 0;
892  if (part_info->part_type != HASH_PARTITION &&
893  part_info->part_expr->unsigned_flag)
894  {
895  List_iterator<partition_element> part_it(part_info->partitions);
896  do
897  {
898  partition_element *part_elem= part_it++;
899 
900  if (part_elem->signed_flag)
901  {
902  my_error(ER_PARTITION_CONST_DOMAIN_ERROR, MYF(0));
903  error= ER_PARTITION_CONST_DOMAIN_ERROR;
904  break;
905  }
906  } while (++i < part_info->num_parts);
907  }
908  return error;
909 }
910 
931 static int
932 init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
933 {
934  TABLE_LIST *table_list;
935  Table_ident *table_ident;
936  SELECT_LEX *select_lex= &lex->select_lex;
937  Name_resolution_context *context= &select_lex->context;
938  /*
939  We will call the parser to create a part_info struct based on the
940  partition string stored in the frm file.
941  We will use a local lex object for this purpose. However we also
942  need to set the Name_resolution_object for this lex object. We
943  do this by using add_table_to_list where we add the table that
944  we're working with to the Name_resolution_context.
945  */
946  thd->lex= lex;
947  lex_start(thd);
948  context->init();
949  if ((!(table_ident= new Table_ident(thd,
950  table->s->table_name,
951  table->s->db, TRUE))) ||
952  (!(table_list= select_lex->add_table_to_list(thd,
953  table_ident,
954  NULL,
955  0))))
956  return TRUE;
957  context->resolve_in_table_list_only(table_list);
958  lex->use_only_table_context= TRUE;
959  table->map= 1; //To ensure correct calculation of const item
960  table->get_fields_in_item_tree= TRUE;
961  table_list->table= table;
962  table_list->cacheable_table= false;
963  return FALSE;
964 }
965 
981 static void
982 end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex)
983 {
984  LEX *lex= thd->lex;
985  table->map= 0;
986  table->get_fields_in_item_tree= FALSE;
987  lex_end(lex);
988  thd->lex= old_lex;
989 }
990 
991 /*
992  The function uses a new feature in fix_fields where the flag
993  GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
994  This field must always be reset before returning from the function
995  since it is used for other purposes as well.
996 
997  SYNOPSIS
998  fix_fields_part_func()
999  thd The thread object
1000  func_expr The item tree reference of the partition function
1001  table The table object
1002  part_info Reference to partitioning data structure
1003  is_sub_part Is the table subpartitioned as well
1004  is_create_table_ind Indicator of whether openfrm was called as part of
1005  CREATE or ALTER TABLE
1006 
1007  RETURN VALUE
1008  TRUE An error occurred, something was wrong with the
1009  partition function.
1010  FALSE Ok, a partition field array was created
1011 
1012  DESCRIPTION
1013  This function is used to build an array of partition fields for the
1014  partitioning function and subpartitioning function. The partitioning
1015  function is an item tree that must reference at least one field in the
1016  table. This is checked first in the parser that the function doesn't
1017  contain non-cacheable parts (like a random function) and by checking
1018  here that the function isn't a constant function.
1019 
1020  Calculate the number of fields in the partition function.
1021  Use it allocate memory for array of Field pointers.
1022  Initialise array of field pointers. Use information set when
1023  calling fix_fields and reset it immediately after.
1024  The get_fields_in_item_tree activates setting of bit in flags
1025  on the field object.
1026 */
1027 
1028 static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
1029  bool is_sub_part, bool is_create_table_ind)
1030 {
1031  partition_info *part_info= table->part_info;
1032  bool result= TRUE;
1033  int error;
1034  LEX *old_lex= thd->lex;
1035  LEX lex;
1036  DBUG_ENTER("fix_fields_part_func");
1037 
1038  if (init_lex_with_single_table(thd, table, &lex))
1039  goto end;
1040 
1041  func_expr->walk(&Item::change_context_processor, 0,
1042  (uchar*) &lex.select_lex.context);
1043  thd->where= "partition function";
1044  /*
1045  In execution we must avoid the use of thd->change_item_tree since
1046  we might release memory before statement is completed. We do this
1047  by temporarily setting the stmt_arena->mem_root to be the mem_root
1048  of the table object, this also ensures that any memory allocated
1049  during fix_fields will not be released at end of execution of this
1050  statement. Thus the item tree will remain valid also in subsequent
1051  executions of this table object. We do however not at the moment
1052  support allocations during execution of val_int so any item class
1053  that does this during val_int must be disallowed as partition
1054  function.
1055  SEE Bug #21658
1056 
1057  This is a tricky call to prepare for since it can have a large number
1058  of interesting side effects, both desirable and undesirable.
1059  */
1060  {
1061  const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
1062  const bool save_agg_func= thd->lex->current_select->agg_func_used();
1063  const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
1064  thd->lex->allow_sum_func= 0;
1065 
1066  error= func_expr->fix_fields(thd, (Item**)&func_expr);
1067 
1068  /*
1069  Restore agg_field/agg_func and allow_sum_func,
1070  fix_fields should not affect mysql_select later, see Bug#46923.
1071  */
1072  thd->lex->current_select->set_non_agg_field_used(save_agg_field);
1073  thd->lex->current_select->set_agg_func_used(save_agg_func);
1074  thd->lex->allow_sum_func= saved_allow_sum_func;
1075  }
1076  if (unlikely(error))
1077  {
1078  DBUG_PRINT("info", ("Field in partition function not part of table"));
1079  clear_field_flag(table);
1080  goto end;
1081  }
1082  if (unlikely(func_expr->const_item()))
1083  {
1084  my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
1085  clear_field_flag(table);
1086  goto end;
1087  }
1088 
1089  /*
1090  We don't allow creating partitions with expressions with non matching
1091  arguments as a (sub)partitioning function,
1092  but we want to allow such expressions when opening existing tables for
1093  easier maintenance. This exception should be deprecated at some point
1094  in future so that we always throw an error.
1095  */
1096  if (func_expr->walk(&Item::check_valid_arguments_processor,
1097  0, NULL))
1098  {
1099  if (is_create_table_ind)
1100  {
1101  my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
1102  goto end;
1103  }
1104  else
1105  push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
1106  ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR,
1107  ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
1108  }
1109 
1110  if ((!is_sub_part) && (error= check_signed_flag(part_info)))
1111  goto end;
1112  result= set_up_field_array(table, is_sub_part);
1113 end:
1114  end_lex_with_single_table(thd, table, old_lex);
1115 #if !defined(DBUG_OFF)
1116  func_expr->walk(&Item::change_context_processor, 0,
1117  (uchar*) 0);
1118 #endif
1119  DBUG_RETURN(result);
1120 }
1121 
1122 
1123 /*
1124  Check that the primary key contains all partition fields if defined
1125 
1126  SYNOPSIS
1127  check_primary_key()
1128  table TABLE object for which partition fields are set-up
1129 
1130  RETURN VALUES
1131  TRUE Not all fields in partitioning function was part
1132  of primary key
1133  FALSE Ok, all fields of partitioning function were part
1134  of primary key
1135 
1136  DESCRIPTION
1137  This function verifies that if there is a primary key that it contains
1138  all the fields of the partition function.
1139  This is a temporary limitation that will hopefully be removed after a
1140  while.
1141 */
1142 
1143 static bool check_primary_key(TABLE *table)
1144 {
1145  uint primary_key= table->s->primary_key;
1146  bool all_fields, some_fields;
1147  bool result= FALSE;
1148  DBUG_ENTER("check_primary_key");
1149 
1150  if (primary_key < MAX_KEY)
1151  {
1152  set_indicator_in_key_fields(table->key_info+primary_key);
1153  check_fields_in_PF(table->part_info->full_part_field_array,
1154  &all_fields, &some_fields);
1155  clear_indicator_in_key_fields(table->key_info+primary_key);
1156  if (unlikely(!all_fields))
1157  {
1158  my_error(ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF,MYF(0),"PRIMARY KEY");
1159  result= TRUE;
1160  }
1161  }
1162  DBUG_RETURN(result);
1163 }
1164 
1165 
1166 /*
1167  Check that unique keys contains all partition fields
1168 
1169  SYNOPSIS
1170  check_unique_keys()
1171  table TABLE object for which partition fields are set-up
1172 
1173  RETURN VALUES
1174  TRUE Not all fields in partitioning function was part
1175  of all unique keys
1176  FALSE Ok, all fields of partitioning function were part
1177  of unique keys
1178 
1179  DESCRIPTION
1180  This function verifies that if there is a unique index that it contains
1181  all the fields of the partition function.
1182  This is a temporary limitation that will hopefully be removed after a
1183  while.
1184 */
1185 
1186 static bool check_unique_keys(TABLE *table)
1187 {
1188  bool all_fields, some_fields;
1189  bool result= FALSE;
1190  uint keys= table->s->keys;
1191  uint i;
1192  DBUG_ENTER("check_unique_keys");
1193 
1194  for (i= 0; i < keys; i++)
1195  {
1196  if (table->key_info[i].flags & HA_NOSAME) //Unique index
1197  {
1198  set_indicator_in_key_fields(table->key_info+i);
1199  check_fields_in_PF(table->part_info->full_part_field_array,
1200  &all_fields, &some_fields);
1201  clear_indicator_in_key_fields(table->key_info+i);
1202  if (unlikely(!all_fields))
1203  {
1204  my_error(ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF,MYF(0),"UNIQUE INDEX");
1205  result= TRUE;
1206  break;
1207  }
1208  }
1209  }
1210  DBUG_RETURN(result);
1211 }
1212 
1213 
1214 /*
1215  An important optimisation is whether a range on a field can select a subset
1216  of the partitions.
1217  A prerequisite for this to happen is that the PF is a growing function OR
1218  a shrinking function.
1219  This can never happen for a multi-dimensional PF. Thus this can only happen
1220  with PF with at most one field involved in the PF.
1221  The idea is that if the function is a growing function and you know that
1222  the field of the PF is 4 <= A <= 6 then we can convert this to a range
1223  in the PF instead by setting the range to PF(4) <= PF(A) <= PF(6). In the
1224  case of RANGE PARTITIONING and LIST PARTITIONING this can be used to
1225  calculate a set of partitions rather than scanning all of them.
1226  Thus the following prerequisites are there to check if sets of partitions
1227  can be found.
1228  1) Only possible for RANGE and LIST partitioning (not for subpartitioning)
1229  2) Only possible if PF only contains 1 field
1230  3) Possible if PF is a growing function of the field
1231  4) Possible if PF is a shrinking function of the field
1232  OBSERVATION:
1233  1) IF f1(A) is a growing function AND f2(A) is a growing function THEN
1234  f1(A) + f2(A) is a growing function
1235  f1(A) * f2(A) is a growing function if f1(A) >= 0 and f2(A) >= 0
1236  2) IF f1(A) is a growing function and f2(A) is a shrinking function THEN
1237  f1(A) / f2(A) is a growing function if f1(A) >= 0 and f2(A) > 0
1238  3) IF A is a growing function then a function f(A) that removes the
1239  least significant portion of A is a growing function
1240  E.g. DATE(datetime) is a growing function
1241  MONTH(datetime) is not a growing/shrinking function
1242  4) IF f1(A) is a growing function and f2(A) is a growing function THEN
1243  f1(f2(A)) and f2(f1(A)) are also growing functions
1244  5) IF f1(A) is a shrinking function and f2(A) is a growing function THEN
1245  f1(f2(A)) is a shrinking function and f2(f1(A)) is a shrinking function
1246  6) f1(A) = A is a growing function
1247  7) f1(A) = A*a + b (where a and b are constants) is a growing function
1248 
1249  By analysing the item tree of the PF we can use these deducements and
1250  derive whether the PF is a growing function or a shrinking function or
1251  neither of it.
1252 
1253  If the PF is range capable then a flag is set on the table object
1254  indicating this to notify that we can use also ranges on the field
1255  of the PF to deduce a set of partitions if the fields of the PF were
1256  not all fully bound.
1257 
1258  SYNOPSIS
1259  check_range_capable_PF()
1260  table TABLE object for which partition fields are set-up
1261 
1262  DESCRIPTION
1263  Support for this is not implemented yet.
1264 */
1265 
1266 void check_range_capable_PF(TABLE *table)
1267 {
1268  DBUG_ENTER("check_range_capable_PF");
1269 
1270  DBUG_VOID_RETURN;
1271 }
1272 
1273 
1288 static bool set_up_partition_bitmaps(THD *thd, partition_info *part_info)
1289 {
1290  uint32 *bitmap_buf;
1291  uint bitmap_bits= part_info->num_subparts?
1292  (part_info->num_subparts* part_info->num_parts):
1293  part_info->num_parts;
1294  uint bitmap_bytes= bitmap_buffer_size(bitmap_bits);
1295  DBUG_ENTER("set_up_partition_bitmaps");
1296 
1297  DBUG_ASSERT(!part_info->bitmaps_are_initialized);
1298 
1299  /* Allocate for both read and lock_partitions */
1300  if (!(bitmap_buf= (uint32*) alloc_root(&part_info->table->mem_root,
1301  bitmap_bytes * 2)))
1302  {
1303  mem_alloc_error(bitmap_bytes * 2);
1304  DBUG_RETURN(TRUE);
1305  }
1306  bitmap_init(&part_info->read_partitions, bitmap_buf, bitmap_bits, FALSE);
1307  /* Use the second half of the allocated buffer for lock_partitions */
1308  bitmap_init(&part_info->lock_partitions, bitmap_buf + (bitmap_bytes / 4),
1309  bitmap_bits, FALSE);
1310  part_info->bitmaps_are_initialized= TRUE;
1311  part_info->set_partition_bitmaps(NULL);
1312  DBUG_RETURN(FALSE);
1313 }
1314 
1315 
1316 /*
1317  Set up partition key maps
1318 
1319  SYNOPSIS
1320  set_up_partition_key_maps()
1321  table TABLE object for which partition fields are set-up
1322  part_info Reference to partitioning data structure
1323 
1324  RETURN VALUES
1325  None
1326 
1327  DESCRIPTION
1328  This function sets up a couple of key maps to be able to quickly check
1329  if an index ever can be used to deduce the partition fields or even
1330  a part of the fields of the partition function.
1331  We set up the following key_map's.
1332  PF = Partition Function
1333  1) All fields of the PF is set even by equal on the first fields in the
1334  key
1335  2) All fields of the PF is set if all fields of the key is set
1336  3) At least one field in the PF is set if all fields is set
1337  4) At least one field in the PF is part of the key
1338 */
1339 
1340 static void set_up_partition_key_maps(TABLE *table,
1341  partition_info *part_info)
1342 {
1343  uint keys= table->s->keys;
1344  uint i;
1345  bool all_fields, some_fields;
1346  DBUG_ENTER("set_up_partition_key_maps");
1347 
1348  part_info->all_fields_in_PF.clear_all();
1349  part_info->all_fields_in_PPF.clear_all();
1350  part_info->all_fields_in_SPF.clear_all();
1351  part_info->some_fields_in_PF.clear_all();
1352  for (i= 0; i < keys; i++)
1353  {
1354  set_indicator_in_key_fields(table->key_info+i);
1355  check_fields_in_PF(part_info->full_part_field_array,
1356  &all_fields, &some_fields);
1357  if (all_fields)
1358  part_info->all_fields_in_PF.set_bit(i);
1359  if (some_fields)
1360  part_info->some_fields_in_PF.set_bit(i);
1361  if (part_info->is_sub_partitioned())
1362  {
1363  check_fields_in_PF(part_info->part_field_array,
1364  &all_fields, &some_fields);
1365  if (all_fields)
1366  part_info->all_fields_in_PPF.set_bit(i);
1367  check_fields_in_PF(part_info->subpart_field_array,
1368  &all_fields, &some_fields);
1369  if (all_fields)
1370  part_info->all_fields_in_SPF.set_bit(i);
1371  }
1372  clear_indicator_in_key_fields(table->key_info+i);
1373  }
1374  DBUG_VOID_RETURN;
1375 }
1376 
1377 
1378 /*
1379  Set up function pointers for partition function
1380 
1381  SYNOPSIS
1382  set_up_partition_func_pointers()
1383  part_info Reference to partitioning data structure
1384 
1385  RETURN VALUE
1386  NONE
1387 
1388  DESCRIPTION
1389  Set-up all function pointers for calculation of partition id,
1390  subpartition id and the upper part in subpartitioning. This is to speed up
1391  execution of get_partition_id which is executed once every record to be
1392  written and deleted and twice for updates.
1393 */
1394 
1395 static void set_up_partition_func_pointers(partition_info *part_info)
1396 {
1397  DBUG_ENTER("set_up_partition_func_pointers");
1398 
1399  if (part_info->is_sub_partitioned())
1400  {
1401  part_info->get_partition_id= get_partition_id_with_sub;
1402  if (part_info->part_type == RANGE_PARTITION)
1403  {
1404  if (part_info->column_list)
1405  part_info->get_part_partition_id= get_partition_id_range_col;
1406  else
1407  part_info->get_part_partition_id= get_partition_id_range;
1408  if (part_info->list_of_subpart_fields)
1409  {
1410  if (part_info->linear_hash_ind)
1411  part_info->get_subpartition_id= get_partition_id_linear_key_sub;
1412  else
1413  part_info->get_subpartition_id= get_partition_id_key_sub;
1414  }
1415  else
1416  {
1417  if (part_info->linear_hash_ind)
1418  part_info->get_subpartition_id= get_partition_id_linear_hash_sub;
1419  else
1420  part_info->get_subpartition_id= get_partition_id_hash_sub;
1421  }
1422  }
1423  else /* LIST Partitioning */
1424  {
1425  if (part_info->column_list)
1426  part_info->get_part_partition_id= get_partition_id_list_col;
1427  else
1428  part_info->get_part_partition_id= get_partition_id_list;
1429  if (part_info->list_of_subpart_fields)
1430  {
1431  if (part_info->linear_hash_ind)
1432  part_info->get_subpartition_id= get_partition_id_linear_key_sub;
1433  else
1434  part_info->get_subpartition_id= get_partition_id_key_sub;
1435  }
1436  else
1437  {
1438  if (part_info->linear_hash_ind)
1439  part_info->get_subpartition_id= get_partition_id_linear_hash_sub;
1440  else
1441  part_info->get_subpartition_id= get_partition_id_hash_sub;
1442  }
1443  }
1444  }
1445  else /* No subpartitioning */
1446  {
1447  part_info->get_part_partition_id= NULL;
1448  part_info->get_subpartition_id= NULL;
1449  if (part_info->part_type == RANGE_PARTITION)
1450  {
1451  if (part_info->column_list)
1452  part_info->get_partition_id= get_partition_id_range_col;
1453  else
1454  part_info->get_partition_id= get_partition_id_range;
1455  }
1456  else if (part_info->part_type == LIST_PARTITION)
1457  {
1458  if (part_info->column_list)
1459  part_info->get_partition_id= get_partition_id_list_col;
1460  else
1461  part_info->get_partition_id= get_partition_id_list;
1462  }
1463  else /* HASH partitioning */
1464  {
1465  if (part_info->list_of_part_fields)
1466  {
1467  if (part_info->linear_hash_ind)
1468  part_info->get_partition_id= get_partition_id_linear_key_nosub;
1469  else
1470  part_info->get_partition_id= get_partition_id_key_nosub;
1471  }
1472  else
1473  {
1474  if (part_info->linear_hash_ind)
1475  part_info->get_partition_id= get_partition_id_linear_hash_nosub;
1476  else
1477  part_info->get_partition_id= get_partition_id_hash_nosub;
1478  }
1479  }
1480  }
1481  /*
1482  We need special functions to handle character sets since they require copy
1483  of field pointers and restore afterwards. For subpartitioned tables we do
1484  the copy and restore individually on the part and subpart parts. For non-
1485  subpartitioned tables we use the same functions as used for the parts part
1486  of subpartioning.
1487  Thus for subpartitioned tables the get_partition_id is always
1488  get_partition_id_with_sub, even when character sets exists.
1489  */
1490  if (part_info->part_charset_field_array)
1491  {
1492  if (part_info->is_sub_partitioned())
1493  {
1494  DBUG_ASSERT(part_info->get_part_partition_id);
1495  if (!part_info->column_list)
1496  {
1497  part_info->get_part_partition_id_charset=
1498  part_info->get_part_partition_id;
1499  part_info->get_part_partition_id= get_part_id_charset_func_part;
1500  }
1501  }
1502  else
1503  {
1504  DBUG_ASSERT(part_info->get_partition_id);
1505  if (!part_info->column_list)
1506  {
1507  part_info->get_part_partition_id_charset= part_info->get_partition_id;
1508  part_info->get_part_partition_id= get_part_id_charset_func_part;
1509  }
1510  }
1511  }
1512  if (part_info->subpart_charset_field_array)
1513  {
1514  DBUG_ASSERT(part_info->get_subpartition_id);
1515  part_info->get_subpartition_id_charset=
1516  part_info->get_subpartition_id;
1517  part_info->get_subpartition_id= get_part_id_charset_func_subpart;
1518  }
1519  DBUG_VOID_RETURN;
1520 }
1521 
1522 
1523 /*
1524  For linear hashing we need a mask which is on the form 2**n - 1 where
1525  2**n >= num_parts. Thus if num_parts is 6 then mask is 2**3 - 1 = 8 - 1 = 7.
1526 
1527  SYNOPSIS
1528  set_linear_hash_mask()
1529  part_info Reference to partitioning data structure
1530  num_parts Number of parts in linear hash partitioning
1531 
1532  RETURN VALUE
1533  NONE
1534 */
1535 
1536 void set_linear_hash_mask(partition_info *part_info, uint num_parts)
1537 {
1538  uint mask;
1539 
1540  for (mask= 1; mask < num_parts; mask<<=1)
1541  ;
1542  part_info->linear_hash_mask= mask - 1;
1543 }
1544 
1545 
1546 /*
1547  This function calculates the partition id provided the result of the hash
1548  function using linear hashing parameters, mask and number of partitions.
1549 
1550  SYNOPSIS
1551  get_part_id_from_linear_hash()
1552  hash_value Hash value calculated by HASH function or KEY function
1553  mask Mask calculated previously by set_linear_hash_mask
1554  num_parts Number of partitions in HASH partitioned part
1555 
1556  RETURN VALUE
1557  part_id The calculated partition identity (starting at 0)
1558 
1559  DESCRIPTION
1560  The partition is calculated according to the theory of linear hashing.
1561  See e.g. Linear hashing: a new tool for file and table addressing,
1562  Reprinted from VLDB-80 in Readings Database Systems, 2nd ed, M. Stonebraker
1563  (ed.), Morgan Kaufmann 1994.
1564 */
1565 
1566 static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask,
1567  uint num_parts)
1568 {
1569  uint32 part_id= (uint32)(hash_value & mask);
1570 
1571  if (part_id >= num_parts)
1572  {
1573  uint new_mask= ((mask + 1) >> 1) - 1;
1574  part_id= (uint32)(hash_value & new_mask);
1575  }
1576  return part_id;
1577 }
1578 
1579 
1580 /*
1581  Check if a particular field is in need of character set
1582  handling for partition functions.
1583 
1584  SYNOPSIS
1585  field_is_partition_charset()
1586  field The field to check
1587 
1588  RETURN VALUES
1589  FALSE Not in need of character set handling
1590  TRUE In need of character set handling
1591 */
1592 
1593 bool field_is_partition_charset(Field *field)
1594 {
1595  if (!(field->type() == MYSQL_TYPE_STRING) &&
1596  !(field->type() == MYSQL_TYPE_VARCHAR))
1597  return FALSE;
1598  {
1599  const CHARSET_INFO *cs= field->charset();
1600  if (!(field->type() == MYSQL_TYPE_STRING) ||
1601  !(cs->state & MY_CS_BINSORT))
1602  return TRUE;
1603  return FALSE;
1604  }
1605 }
1606 
1607 
1608 /*
1609  Check that partition function doesn't contain any forbidden
1610  character sets and collations.
1611 
1612  SYNOPSIS
1613  check_part_func_fields()
1614  ptr Array of Field pointers
1615  ok_with_charsets Will we report allowed charset
1616  fields as ok
1617  RETURN VALUES
1618  FALSE Success
1619  TRUE Error
1620 
1621  DESCRIPTION
1622  We will check in this routine that the fields of the partition functions
1623  do not contain unallowed parts. It can also be used to check if there
1624  are fields that require special care by calling my_strnxfrm before
1625  calling the functions to calculate partition id.
1626 */
1627 
1628 bool check_part_func_fields(Field **ptr, bool ok_with_charsets)
1629 {
1630  Field *field;
1631  DBUG_ENTER("check_part_func_fields");
1632 
1633  while ((field= *(ptr++)))
1634  {
1635  /*
1636  For CHAR/VARCHAR fields we need to take special precautions.
1637  Binary collation with CHAR is automatically supported. Other
1638  types need some kind of standardisation function handling
1639  */
1640  if (field_is_partition_charset(field))
1641  {
1642  const CHARSET_INFO *cs= field->charset();
1643  if (!ok_with_charsets ||
1644  cs->mbmaxlen > 1 ||
1645  cs->strxfrm_multiply > 1)
1646  {
1647  DBUG_RETURN(TRUE);
1648  }
1649  }
1650  }
1651  DBUG_RETURN(FALSE);
1652 }
1653 
1654 
1655 /*
1656  fix partition functions
1657 
1658  SYNOPSIS
1659  fix_partition_func()
1660  thd The thread object
1661  table TABLE object for which partition fields are set-up
1662  is_create_table_ind Indicator of whether openfrm was called as part of
1663  CREATE or ALTER TABLE
1664 
1665  RETURN VALUE
1666  TRUE Error
1667  FALSE Success
1668 
1669  DESCRIPTION
1670  The name parameter contains the full table name and is used to get the
1671  database name of the table which is used to set-up a correct
1672  TABLE_LIST object for use in fix_fields.
1673 
1674 NOTES
1675  This function is called as part of opening the table by opening the .frm
1676  file. It is a part of CREATE TABLE to do this so it is quite permissible
1677  that errors due to erroneus syntax isn't found until we come here.
1678  If the user has used a non-existing field in the table is one such example
1679  of an error that is not discovered until here.
1680 */
1681 
1682 bool fix_partition_func(THD *thd, TABLE *table,
1683  bool is_create_table_ind)
1684 {
1685  bool result= TRUE;
1686  partition_info *part_info= table->part_info;
1687  enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
1688  DBUG_ENTER("fix_partition_func");
1689 
1690  if (part_info->fixed)
1691  {
1692  DBUG_RETURN(FALSE);
1693  }
1694  thd->mark_used_columns= MARK_COLUMNS_NONE;
1695  DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
1696 
1697  if (!is_create_table_ind ||
1698  thd->lex->sql_command != SQLCOM_CREATE_TABLE)
1699  {
1700  if (partition_default_handling(table, part_info,
1701  is_create_table_ind,
1702  table->s->normalized_path.str))
1703  {
1704  DBUG_RETURN(TRUE);
1705  }
1706  }
1707  if (part_info->is_sub_partitioned())
1708  {
1709  DBUG_ASSERT(part_info->subpart_type == HASH_PARTITION);
1710  /*
1711  Subpartition is defined. We need to verify that subpartitioning
1712  function is correct.
1713  */
1714  if (part_info->linear_hash_ind)
1715  set_linear_hash_mask(part_info, part_info->num_subparts);
1716  if (part_info->list_of_subpart_fields)
1717  {
1718  List_iterator<char> it(part_info->subpart_field_list);
1719  if (unlikely(handle_list_of_fields(it, table, part_info, TRUE)))
1720  goto end;
1721  }
1722  else
1723  {
1724  if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr,
1725  table, TRUE, is_create_table_ind)))
1726  goto end;
1727  if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT))
1728  {
1729  part_info->report_part_expr_error(TRUE);
1730  goto end;
1731  }
1732  }
1733  }
1734  DBUG_ASSERT(part_info->part_type != NOT_A_PARTITION);
1735  /*
1736  Partition is defined. We need to verify that partitioning
1737  function is correct.
1738  */
1739  if (part_info->part_type == HASH_PARTITION)
1740  {
1741  if (part_info->linear_hash_ind)
1742  set_linear_hash_mask(part_info, part_info->num_parts);
1743  if (part_info->list_of_part_fields)
1744  {
1745  List_iterator<char> it(part_info->part_field_list);
1746  if (unlikely(handle_list_of_fields(it, table, part_info, FALSE)))
1747  goto end;
1748  }
1749  else
1750  {
1751  if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
1752  table, FALSE, is_create_table_ind)))
1753  goto end;
1754  if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
1755  {
1756  part_info->report_part_expr_error(FALSE);
1757  goto end;
1758  }
1759  }
1760  part_info->fixed= TRUE;
1761  }
1762  else
1763  {
1764  const char *error_str;
1765  if (part_info->column_list)
1766  {
1767  List_iterator<char> it(part_info->part_field_list);
1768  if (unlikely(handle_list_of_fields(it, table, part_info, FALSE)))
1769  goto end;
1770  }
1771  else
1772  {
1773  if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
1774  table, FALSE, is_create_table_ind)))
1775  goto end;
1776  }
1777  part_info->fixed= TRUE;
1778  if (part_info->part_type == RANGE_PARTITION)
1779  {
1780  error_str= partition_keywords[PKW_RANGE].str;
1781  if (unlikely(part_info->check_range_constants(thd)))
1782  goto end;
1783  }
1784  else if (part_info->part_type == LIST_PARTITION)
1785  {
1786  error_str= partition_keywords[PKW_LIST].str;
1787  if (unlikely(part_info->check_list_constants(thd)))
1788  goto end;
1789  }
1790  else
1791  {
1792  DBUG_ASSERT(0);
1793  my_error(ER_INCONSISTENT_PARTITION_INFO_ERROR, MYF(0));
1794  goto end;
1795  }
1796  if (unlikely(part_info->num_parts < 1))
1797  {
1798  my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str);
1799  goto end;
1800  }
1801  if (unlikely(!part_info->column_list &&
1802  part_info->part_expr->result_type() != INT_RESULT))
1803  {
1804  part_info->report_part_expr_error(FALSE);
1805  goto end;
1806  }
1807  }
1808  if (((part_info->part_type != HASH_PARTITION ||
1809  part_info->list_of_part_fields == FALSE) &&
1810  !part_info->column_list &&
1811  check_part_func_fields(part_info->part_field_array, TRUE)) ||
1812  (part_info->list_of_subpart_fields == FALSE &&
1813  part_info->is_sub_partitioned() &&
1814  check_part_func_fields(part_info->subpart_field_array, TRUE)))
1815  {
1816  /*
1817  Range/List/HASH (but not KEY) and not COLUMNS or HASH subpartitioning
1818  with columns in the partitioning expression using unallowed charset.
1819  */
1820  my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
1821  goto end;
1822  }
1823  if (unlikely(create_full_part_field_array(thd, table, part_info)))
1824  goto end;
1825  if (unlikely(check_primary_key(table)))
1826  goto end;
1827  if (unlikely((!(table->s->db_type()->partition_flags &&
1828  (table->s->db_type()->partition_flags() & HA_CAN_PARTITION_UNIQUE))) &&
1829  check_unique_keys(table)))
1830  goto end;
1831  if (unlikely(set_up_partition_bitmaps(thd, part_info)))
1832  goto end;
1833  if (unlikely(part_info->set_up_charset_field_preps()))
1834  {
1835  my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
1836  goto end;
1837  }
1838  if (unlikely(part_info->check_partition_field_length()))
1839  {
1840  my_error(ER_PARTITION_FIELDS_TOO_LONG, MYF(0));
1841  goto end;
1842  }
1843  check_range_capable_PF(table);
1844  set_up_partition_key_maps(table, part_info);
1845  set_up_partition_func_pointers(part_info);
1846  set_up_range_analysis_info(part_info);
1847  table->file->set_part_info(part_info, FALSE);
1848  result= FALSE;
1849 end:
1850  thd->mark_used_columns= save_mark_used_columns;
1851  DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
1852  DBUG_RETURN(result);
1853 }
1854 
1855 
1856 /*
1857  The code below is support routines for the reverse parsing of the
1858  partitioning syntax. This feature is very useful to generate syntax for
1859  all default values to avoid all default checking when opening the frm
1860  file. It is also used when altering the partitioning by use of various
1861  ALTER TABLE commands. Finally it is used for SHOW CREATE TABLES.
1862 */
1863 
1864 static int add_write(File fptr, const char *buf, uint len)
1865 {
1866  uint ret_code= mysql_file_write(fptr, (const uchar*)buf, len, MYF(MY_FNABP));
1867 
1868  if (likely(ret_code == 0))
1869  return 0;
1870  else
1871  return 1;
1872 }
1873 
1874 static int add_string_object(File fptr, String *string)
1875 {
1876  return add_write(fptr, string->ptr(), string->length());
1877 }
1878 
1879 static int add_string(File fptr, const char *string)
1880 {
1881  return add_write(fptr, string, strlen(string));
1882 }
1883 
1884 static int add_string_len(File fptr, const char *string, uint len)
1885 {
1886  return add_write(fptr, string, len);
1887 }
1888 
1889 static int add_space(File fptr)
1890 {
1891  return add_string(fptr, space_str);
1892 }
1893 
1894 static int add_comma(File fptr)
1895 {
1896  return add_string(fptr, comma_str);
1897 }
1898 
1899 static int add_equal(File fptr)
1900 {
1901  return add_string(fptr, equal_str);
1902 }
1903 
1904 static int add_end_parenthesis(File fptr)
1905 {
1906  return add_string(fptr, end_paren_str);
1907 }
1908 
1909 static int add_begin_parenthesis(File fptr)
1910 {
1911  return add_string(fptr, begin_paren_str);
1912 }
1913 
1914 static int add_part_key_word(File fptr, const char *key_string)
1915 {
1916  int err= add_string(fptr, key_string);
1917  err+= add_space(fptr);
1918  return err;
1919 }
1920 
1921 static int add_partition(File fptr)
1922 {
1923  char buff[22];
1924  strxmov(buff, part_str, space_str, NullS);
1925  return add_string(fptr, buff);
1926 }
1927 
1928 static int add_subpartition(File fptr)
1929 {
1930  int err= add_string(fptr, sub_str);
1931 
1932  return err + add_partition(fptr);
1933 }
1934 
1935 static int add_partition_by(File fptr)
1936 {
1937  char buff[22];
1938  strxmov(buff, part_str, space_str, by_str, space_str, NullS);
1939  return add_string(fptr, buff);
1940 }
1941 
1942 static int add_subpartition_by(File fptr)
1943 {
1944  int err= add_string(fptr, sub_str);
1945 
1946  return err + add_partition_by(fptr);
1947 }
1948 
1949 static int add_part_field_list(File fptr, List<char> field_list)
1950 {
1951  uint i, num_fields;
1952  int err= 0;
1953 
1954  List_iterator<char> part_it(field_list);
1955  num_fields= field_list.elements;
1956  i= 0;
1957  err+= add_begin_parenthesis(fptr);
1958  while (i < num_fields)
1959  {
1960  const char *field_str= part_it++;
1961  String field_string("", 0, system_charset_info);
1962  THD *thd= current_thd;
1963  ulonglong save_options= thd->variables.option_bits;
1964  thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE;
1965  append_identifier(thd, &field_string, field_str,
1966  strlen(field_str));
1967  thd->variables.option_bits= save_options;
1968  err+= add_string_object(fptr, &field_string);
1969  if (i != (num_fields-1))
1970  err+= add_comma(fptr);
1971  i++;
1972  }
1973  err+= add_end_parenthesis(fptr);
1974  return err;
1975 }
1976 
1977 static int add_name_string(File fptr, const char *name)
1978 {
1979  int err;
1980  String name_string("", 0, system_charset_info);
1981  THD *thd= current_thd;
1982  ulonglong save_options= thd->variables.option_bits;
1983  thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE;
1984  append_identifier(thd, &name_string, name,
1985  strlen(name));
1986  thd->variables.option_bits= save_options;
1987  err= add_string_object(fptr, &name_string);
1988  return err;
1989 }
1990 
1991 static int add_int(File fptr, longlong number)
1992 {
1993  char buff[32];
1994  llstr(number, buff);
1995  return add_string(fptr, buff);
1996 }
1997 
1998 static int add_uint(File fptr, ulonglong number)
1999 {
2000  char buff[32];
2001  longlong2str(number, buff, 10);
2002  return add_string(fptr, buff);
2003 }
2004 
2005 /*
2006  Must escape strings in partitioned tables frm-files,
2007  parsing it later with mysql_unpack_partition will fail otherwise.
2008 */
2009 static int add_quoted_string(File fptr, const char *quotestr)
2010 {
2011  String orgstr(quotestr, system_charset_info);
2012  String escapedstr;
2013  int err= add_string(fptr, "'");
2014  err+= append_escaped(&escapedstr, &orgstr);
2015  err+= add_string(fptr, escapedstr.c_ptr_safe());
2016  return err + add_string(fptr, "'");
2017 }
2018 
2026 void truncate_partition_filename(char *path)
2027 {
2028  if (path)
2029  {
2030  char* last_slash= strrchr(path, FN_LIBCHAR);
2031 
2032  if (!last_slash)
2033  last_slash= strrchr(path, FN_LIBCHAR2);
2034 
2035  if (last_slash)
2036  {
2037  /* Look for a partition-type filename */
2038  for (char* pound= strchr(last_slash, '#');
2039  pound; pound = strchr(pound + 1, '#'))
2040  {
2041  if ((pound[1] == 'P' || pound[1] == 'p') && pound[2] == '#')
2042  {
2043  last_slash[0] = '\0'; /* truncate the file name */
2044  break;
2045  }
2046  }
2047  }
2048  }
2049 }
2050 
2051 
2063 static int add_keyword_path(File fptr, const char *keyword,
2064  const char *path)
2065 {
2066  int err= add_string(fptr, keyword);
2067 
2068  err+= add_space(fptr);
2069  err+= add_equal(fptr);
2070  err+= add_space(fptr);
2071 
2072  char temp_path[FN_REFLEN];
2073  strcpy(temp_path, path);
2074 #ifdef __WIN__
2075  /* Convert \ to / to be able to create table on unix */
2076  char *pos, *end;
2077  uint length= strlen(temp_path);
2078  for (pos= temp_path, end= pos+length ; pos < end ; pos++)
2079  {
2080  if (*pos == '\\')
2081  *pos = '/';
2082  }
2083 #endif
2084 
2085  /*
2086  If the partition file name with its "#P#" identifier
2087  is found after the last slash, truncate that filename.
2088  */
2089  truncate_partition_filename(temp_path);
2090 
2091  err+= add_quoted_string(fptr, temp_path);
2092 
2093  return err + add_space(fptr);
2094 }
2095 
2096 static int add_keyword_string(File fptr, const char *keyword,
2097  bool should_use_quotes,
2098  const char *keystr)
2099 {
2100  int err= add_string(fptr, keyword);
2101 
2102  err+= add_space(fptr);
2103  err+= add_equal(fptr);
2104  err+= add_space(fptr);
2105  if (should_use_quotes)
2106  err+= add_quoted_string(fptr, keystr);
2107  else
2108  err+= add_string(fptr, keystr);
2109  return err + add_space(fptr);
2110 }
2111 
2112 static int add_keyword_int(File fptr, const char *keyword, longlong num)
2113 {
2114  int err= add_string(fptr, keyword);
2115 
2116  err+= add_space(fptr);
2117  err+= add_equal(fptr);
2118  err+= add_space(fptr);
2119  err+= add_int(fptr, num);
2120  return err + add_space(fptr);
2121 }
2122 
2123 static int add_engine(File fptr, handlerton *engine_type)
2124 {
2125  const char *engine_str= ha_resolve_storage_engine_name(engine_type);
2126  DBUG_PRINT("info", ("ENGINE: %s", engine_str));
2127  int err= add_string(fptr, "ENGINE = ");
2128  return err + add_string(fptr, engine_str);
2129 }
2130 
2131 static int add_partition_options(File fptr, partition_element *p_elem)
2132 {
2133  int err= 0;
2134 
2135  err+= add_space(fptr);
2136  if (p_elem->tablespace_name)
2137  err+= add_keyword_string(fptr,"TABLESPACE", FALSE,
2138  p_elem->tablespace_name);
2139  if (p_elem->nodegroup_id != UNDEF_NODEGROUP)
2140  err+= add_keyword_int(fptr,"NODEGROUP",(longlong)p_elem->nodegroup_id);
2141  if (p_elem->part_max_rows)
2142  err+= add_keyword_int(fptr,"MAX_ROWS",(longlong)p_elem->part_max_rows);
2143  if (p_elem->part_min_rows)
2144  err+= add_keyword_int(fptr,"MIN_ROWS",(longlong)p_elem->part_min_rows);
2145  if (!(current_thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
2146  {
2147  if (p_elem->data_file_name)
2148  err+= add_keyword_path(fptr, "DATA DIRECTORY", p_elem->data_file_name);
2149  if (p_elem->index_file_name)
2150  err+= add_keyword_path(fptr, "INDEX DIRECTORY", p_elem->index_file_name);
2151  }
2152  if (p_elem->part_comment)
2153  err+= add_keyword_string(fptr, "COMMENT", TRUE, p_elem->part_comment);
2154  return err + add_engine(fptr,p_elem->engine_type);
2155 }
2156 
2157 
2158 /*
2159  Check partition fields for result type and if they need
2160  to check the character set.
2161 
2162  SYNOPSIS
2163  check_part_field()
2164  sql_type Type provided by user
2165  field_name Name of field, used for error handling
2166  result_type Out value: Result type of field
2167  need_cs_check Out value: Do we need character set check
2168 
2169  RETURN VALUES
2170  TRUE Error
2171  FALSE Ok
2172 */
2173 
2174 static int check_part_field(enum_field_types sql_type,
2175  const char *field_name,
2176  Item_result *result_type,
2177  bool *need_cs_check)
2178 {
2179  if (sql_type >= MYSQL_TYPE_TINY_BLOB &&
2180  sql_type <= MYSQL_TYPE_BLOB)
2181  {
2182  my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0));
2183  return TRUE;
2184  }
2185  switch (sql_type)
2186  {
2187  case MYSQL_TYPE_TINY:
2188  case MYSQL_TYPE_SHORT:
2189  case MYSQL_TYPE_LONG:
2190  case MYSQL_TYPE_LONGLONG:
2191  case MYSQL_TYPE_INT24:
2192  *result_type= INT_RESULT;
2193  *need_cs_check= FALSE;
2194  return FALSE;
2195  case MYSQL_TYPE_NEWDATE:
2196  case MYSQL_TYPE_DATE:
2197  case MYSQL_TYPE_TIME:
2198  case MYSQL_TYPE_DATETIME:
2199  case MYSQL_TYPE_TIME2:
2200  case MYSQL_TYPE_DATETIME2:
2201  *result_type= STRING_RESULT;
2202  *need_cs_check= TRUE;
2203  return FALSE;
2204  case MYSQL_TYPE_VARCHAR:
2205  case MYSQL_TYPE_STRING:
2206  case MYSQL_TYPE_VAR_STRING:
2207  *result_type= STRING_RESULT;
2208  *need_cs_check= TRUE;
2209  return FALSE;
2210  case MYSQL_TYPE_NEWDECIMAL:
2211  case MYSQL_TYPE_DECIMAL:
2212  case MYSQL_TYPE_TIMESTAMP:
2213  case MYSQL_TYPE_TIMESTAMP2:
2214  case MYSQL_TYPE_NULL:
2215  case MYSQL_TYPE_FLOAT:
2216  case MYSQL_TYPE_DOUBLE:
2217  case MYSQL_TYPE_BIT:
2218  case MYSQL_TYPE_ENUM:
2219  case MYSQL_TYPE_SET:
2220  case MYSQL_TYPE_GEOMETRY:
2221  goto error;
2222  default:
2223  goto error;
2224  }
2225 error:
2226  my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0),
2227  field_name);
2228  return TRUE;
2229 }
2230 
2231 
2232 /*
2233  Find the given field's Create_field object using name of field
2234 
2235  SYNOPSIS
2236  get_sql_field()
2237  field_name Field name
2238  alter_info Info from ALTER TABLE/CREATE TABLE
2239 
2240  RETURN VALUE
2241  sql_field Object filled in by parser about field
2242  NULL No field found
2243 */
2244 
2245 static Create_field* get_sql_field(char *field_name,
2246  Alter_info *alter_info)
2247 {
2248  List_iterator<Create_field> it(alter_info->create_list);
2249  Create_field *sql_field;
2250  DBUG_ENTER("get_sql_field");
2251 
2252  while ((sql_field= it++))
2253  {
2254  if (!(my_strcasecmp(system_charset_info,
2255  sql_field->field_name,
2256  field_name)))
2257  {
2258  DBUG_RETURN(sql_field);
2259  }
2260  }
2261  DBUG_RETURN(NULL);
2262 }
2263 
2264 
2265 static int add_column_list_values(File fptr, partition_info *part_info,
2266  part_elem_value *list_value,
2267  HA_CREATE_INFO *create_info,
2268  Alter_info *alter_info)
2269 {
2270  int err= 0;
2271  uint i;
2272  List_iterator<char> it(part_info->part_field_list);
2273  uint num_elements= part_info->part_field_list.elements;
2274  bool use_parenthesis= (part_info->part_type == LIST_PARTITION &&
2275  part_info->num_columns > 1U);
2276 
2277  if (use_parenthesis)
2278  err+= add_begin_parenthesis(fptr);
2279  for (i= 0; i < num_elements; i++)
2280  {
2281  part_column_list_val *col_val= &list_value->col_val_array[i];
2282  char *field_name= it++;
2283  if (col_val->max_value)
2284  err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
2285  else if (col_val->null_value)
2286  err+= add_string(fptr, "NULL");
2287  else
2288  {
2289  char buffer[MAX_KEY_LENGTH];
2290  String str(buffer, sizeof(buffer), &my_charset_bin);
2291  Item *item_expr= col_val->item_expression;
2292  if (item_expr->null_value)
2293  err+= add_string(fptr, "NULL");
2294  else
2295  {
2296  String *res;
2297  const CHARSET_INFO *field_cs;
2298  bool need_cs_check= FALSE;
2299  Item_result result_type= STRING_RESULT;
2300 
2301  /*
2302  This function is called at a very early stage, even before
2303  we have prepared the sql_field objects. Thus we have to
2304  find the proper sql_field object and get the character set
2305  from that object.
2306  */
2307  if (create_info)
2308  {
2309  Create_field *sql_field;
2310 
2311  if (!(sql_field= get_sql_field(field_name,
2312  alter_info)))
2313  {
2314  my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
2315  return 1;
2316  }
2317  if (check_part_field(sql_field->sql_type,
2318  sql_field->field_name,
2319  &result_type,
2320  &need_cs_check))
2321  return 1;
2322  if (need_cs_check)
2323  field_cs= get_sql_field_charset(sql_field, create_info);
2324  else
2325  field_cs= NULL;
2326  }
2327  else
2328  {
2329  Field *field= part_info->part_field_array[i];
2330  result_type= field->result_type();
2331  if (check_part_field(field->real_type(),
2332  field->field_name,
2333  &result_type,
2334  &need_cs_check))
2335  return 1;
2336  DBUG_ASSERT(result_type == field->result_type());
2337  if (need_cs_check)
2338  field_cs= field->charset();
2339  else
2340  field_cs= NULL;
2341  }
2342  if (result_type != item_expr->result_type())
2343  {
2344  my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
2345  return 1;
2346  }
2347  if (field_cs && field_cs != item_expr->collation.collation)
2348  {
2349  if (!(item_expr= convert_charset_partition_constant(item_expr,
2350  field_cs)))
2351  {
2352  my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
2353  return 1;
2354  }
2355  }
2356  {
2357  String val_conv;
2358  val_conv.set_charset(system_charset_info);
2359  res= item_expr->val_str(&str);
2360  if (get_cs_converted_part_value_from_string(current_thd,
2361  item_expr, res,
2362  &val_conv, field_cs,
2363  (bool)(alter_info != NULL)))
2364  return 1;
2365  err+= add_string_object(fptr, &val_conv);
2366  }
2367  }
2368  }
2369  if (i != (num_elements - 1))
2370  err+= add_string(fptr, comma_str);
2371  }
2372  if (use_parenthesis)
2373  err+= add_end_parenthesis(fptr);
2374  return err;
2375 }
2376 
2377 static int add_partition_values(File fptr, partition_info *part_info,
2378  partition_element *p_elem,
2379  HA_CREATE_INFO *create_info,
2380  Alter_info *alter_info)
2381 {
2382  int err= 0;
2383 
2384  if (part_info->part_type == RANGE_PARTITION)
2385  {
2386  err+= add_string(fptr, " VALUES LESS THAN ");
2387  if (part_info->column_list)
2388  {
2389  List_iterator<part_elem_value> list_val_it(p_elem->list_val_list);
2390  part_elem_value *list_value= list_val_it++;
2391  err+= add_begin_parenthesis(fptr);
2392  err+= add_column_list_values(fptr, part_info, list_value,
2393  create_info, alter_info);
2394  err+= add_end_parenthesis(fptr);
2395  }
2396  else
2397  {
2398  if (!p_elem->max_value)
2399  {
2400  err+= add_begin_parenthesis(fptr);
2401  if (p_elem->signed_flag)
2402  err+= add_int(fptr, p_elem->range_value);
2403  else
2404  err+= add_uint(fptr, p_elem->range_value);
2405  err+= add_end_parenthesis(fptr);
2406  }
2407  else
2408  err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
2409  }
2410  }
2411  else if (part_info->part_type == LIST_PARTITION)
2412  {
2413  uint i;
2414  List_iterator<part_elem_value> list_val_it(p_elem->list_val_list);
2415  err+= add_string(fptr, " VALUES IN ");
2416  uint num_items= p_elem->list_val_list.elements;
2417 
2418  err+= add_begin_parenthesis(fptr);
2419  if (p_elem->has_null_value)
2420  {
2421  err+= add_string(fptr, "NULL");
2422  if (num_items == 0)
2423  {
2424  err+= add_end_parenthesis(fptr);
2425  goto end;
2426  }
2427  err+= add_comma(fptr);
2428  }
2429  i= 0;
2430  do
2431  {
2432  part_elem_value *list_value= list_val_it++;
2433 
2434  if (part_info->column_list)
2435  err+= add_column_list_values(fptr, part_info, list_value,
2436  create_info, alter_info);
2437  else
2438  {
2439  if (!list_value->unsigned_flag)
2440  err+= add_int(fptr, list_value->value);
2441  else
2442  err+= add_uint(fptr, list_value->value);
2443  }
2444  if (i != (num_items-1))
2445  err+= add_comma(fptr);
2446  } while (++i < num_items);
2447  err+= add_end_parenthesis(fptr);
2448  }
2449 end:
2450  return err;
2451 }
2452 
2453 
2467 static int add_key_with_algorithm(File fptr, partition_info *part_info,
2468  const char *current_comment_start)
2469 {
2470  int err= 0;
2471  err+= add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
2472 
2473  /*
2474  current_comment_start is given when called from SHOW CREATE TABLE,
2475  Then only add ALGORITHM = 1, not the default 2 or non-set 0!
2476  For .frm current_comment_start is NULL, then add ALGORITHM if != 0.
2477  */
2478  if (part_info->key_algorithm == partition_info::KEY_ALGORITHM_51 || // SHOW
2479  (!current_comment_start && // .frm
2480  (part_info->key_algorithm != partition_info::KEY_ALGORITHM_NONE)))
2481  {
2482  /* If we already are within a comment, end that comment first. */
2483  if (current_comment_start)
2484  err+= add_string(fptr, "*/ ");
2485  err+= add_string(fptr, "/*!50611 ");
2486  err+= add_part_key_word(fptr, partition_keywords[PKW_ALGORITHM].str);
2487  err+= add_equal(fptr);
2488  err+= add_space(fptr);
2489  err+= add_int(fptr, part_info->key_algorithm);
2490  err+= add_space(fptr);
2491  err+= add_string(fptr, "*/ ");
2492  if (current_comment_start)
2493  {
2494  /* Skip new line. */
2495  if (current_comment_start[0] == '\n')
2496  current_comment_start++;
2497  err+= add_string(fptr, current_comment_start);
2498  err+= add_space(fptr);
2499  }
2500  }
2501  return err;
2502 }
2503 
2504 
2505 /*
2506  Generate the partition syntax from the partition data structure.
2507  Useful for support of generating defaults, SHOW CREATE TABLES
2508  and easy partition management.
2509 
2510  SYNOPSIS
2511  generate_partition_syntax()
2512  part_info The partitioning data structure
2513  buf_length A pointer to the returned buffer length
2514  use_sql_alloc Allocate buffer from sql_alloc if true
2515  otherwise use my_malloc
2516  show_partition_options Should we display partition options
2517  create_info Info generated by parser
2518  alter_info Info generated by parser
2519 
2520  RETURN VALUES
2521  NULL error
2522  buf, buf_length Buffer and its length
2523 
2524  DESCRIPTION
2525  Here we will generate the full syntax for the given command where all
2526  defaults have been expanded. By so doing the it is also possible to
2527  make lots of checks of correctness while at it.
2528  This could will also be reused for SHOW CREATE TABLES and also for all
2529  type ALTER TABLE commands focusing on changing the PARTITION structure
2530  in any fashion.
2531 
2532  The implementation writes the syntax to a temporary file (essentially
2533  an abstraction of a dynamic array) and if all writes goes well it
2534  allocates a buffer and writes the syntax into this one and returns it.
2535 
2536  As a security precaution the file is deleted before writing into it. This
2537  means that no other processes on the machine can open and read the file
2538  while this processing is ongoing.
2539 
2540  The code is optimised for minimal code size since it is not used in any
2541  common queries.
2542 */
2543 
2544 char *generate_partition_syntax(partition_info *part_info,
2545  uint *buf_length,
2546  bool use_sql_alloc,
2547  bool show_partition_options,
2548  HA_CREATE_INFO *create_info,
2549  Alter_info *alter_info,
2550  const char *current_comment_start)
2551 {
2552  uint i,j, tot_num_parts, num_subparts;
2553  partition_element *part_elem;
2554  ulonglong buffer_length;
2555  char path[FN_REFLEN];
2556  int err= 0;
2557  List_iterator<partition_element> part_it(part_info->partitions);
2558  File fptr;
2559  char *buf= NULL; //Return buffer
2560  DBUG_ENTER("generate_partition_syntax");
2561 
2562  if (unlikely(((fptr= create_temp_file(path,mysql_tmpdir,"psy",
2563  O_RDWR | O_BINARY | O_TRUNC |
2564  O_TEMPORARY, MYF(MY_WME)))) < 0))
2565  DBUG_RETURN(NULL);
2566 #ifndef __WIN__
2567  unlink(path);
2568 #endif
2569  err+= add_space(fptr);
2570  err+= add_partition_by(fptr);
2571  switch (part_info->part_type)
2572  {
2573  case RANGE_PARTITION:
2574  err+= add_part_key_word(fptr, partition_keywords[PKW_RANGE].str);
2575  break;
2576  case LIST_PARTITION:
2577  err+= add_part_key_word(fptr, partition_keywords[PKW_LIST].str);
2578  break;
2579  case HASH_PARTITION:
2580  if (part_info->linear_hash_ind)
2581  err+= add_string(fptr, partition_keywords[PKW_LINEAR].str);
2582  if (part_info->list_of_part_fields)
2583  {
2584  err+= add_key_with_algorithm(fptr, part_info,
2585  current_comment_start);
2586  err+= add_part_field_list(fptr, part_info->part_field_list);
2587  }
2588  else
2589  err+= add_part_key_word(fptr, partition_keywords[PKW_HASH].str);
2590  break;
2591  default:
2592  DBUG_ASSERT(0);
2593  /* We really shouldn't get here, no use in continuing from here */
2594  my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
2595  DBUG_RETURN(NULL);
2596  }
2597  if (part_info->part_expr)
2598  {
2599  err+= add_begin_parenthesis(fptr);
2600  err+= add_string_len(fptr, part_info->part_func_string,
2601  part_info->part_func_len);
2602  err+= add_end_parenthesis(fptr);
2603  }
2604  else if (part_info->column_list)
2605  {
2606  err+= add_string(fptr, partition_keywords[PKW_COLUMNS].str);
2607  err+= add_part_field_list(fptr, part_info->part_field_list);
2608  }
2609  if ((!part_info->use_default_num_partitions) &&
2610  part_info->use_default_partitions)
2611  {
2612  err+= add_string(fptr, "\n");
2613  err+= add_string(fptr, "PARTITIONS ");
2614  err+= add_int(fptr, part_info->num_parts);
2615  }
2616  if (part_info->is_sub_partitioned())
2617  {
2618  err+= add_string(fptr, "\n");
2619  err+= add_subpartition_by(fptr);
2620  /* Must be hash partitioning for subpartitioning */
2621  if (part_info->linear_hash_ind)
2622  err+= add_string(fptr, partition_keywords[PKW_LINEAR].str);
2623  if (part_info->list_of_subpart_fields)
2624  {
2625  err+= add_key_with_algorithm(fptr, part_info,
2626  current_comment_start);
2627  err+= add_part_field_list(fptr, part_info->subpart_field_list);
2628  }
2629  else
2630  err+= add_part_key_word(fptr, partition_keywords[PKW_HASH].str);
2631  if (part_info->subpart_expr)
2632  {
2633  err+= add_begin_parenthesis(fptr);
2634  err+= add_string_len(fptr, part_info->subpart_func_string,
2635  part_info->subpart_func_len);
2636  err+= add_end_parenthesis(fptr);
2637  }
2638  if ((!part_info->use_default_num_subpartitions) &&
2639  part_info->use_default_subpartitions)
2640  {
2641  err+= add_string(fptr, "\n");
2642  err+= add_string(fptr, "SUBPARTITIONS ");
2643  err+= add_int(fptr, part_info->num_subparts);
2644  }
2645  }
2646  tot_num_parts= part_info->partitions.elements;
2647  num_subparts= part_info->num_subparts;
2648 
2649  if (!part_info->use_default_partitions)
2650  {
2651  bool first= TRUE;
2652  err+= add_string(fptr, "\n");
2653  err+= add_begin_parenthesis(fptr);
2654  i= 0;
2655  do
2656  {
2657  part_elem= part_it++;
2658  if (part_elem->part_state != PART_TO_BE_DROPPED &&
2659  part_elem->part_state != PART_REORGED_DROPPED)
2660  {
2661  if (!first)
2662  {
2663  err+= add_comma(fptr);
2664  err+= add_string(fptr, "\n");
2665  err+= add_space(fptr);
2666  }
2667  first= FALSE;
2668  err+= add_partition(fptr);
2669  err+= add_name_string(fptr, part_elem->partition_name);
2670  err+= add_partition_values(fptr, part_info, part_elem,
2671  create_info, alter_info);
2672  if (!part_info->is_sub_partitioned() ||
2673  part_info->use_default_subpartitions)
2674  {
2675  if (show_partition_options)
2676  err+= add_partition_options(fptr, part_elem);
2677  }
2678  else
2679  {
2680  err+= add_string(fptr, "\n");
2681  err+= add_space(fptr);
2682  err+= add_begin_parenthesis(fptr);
2683  List_iterator<partition_element> sub_it(part_elem->subpartitions);
2684  j= 0;
2685  do
2686  {
2687  part_elem= sub_it++;
2688  err+= add_subpartition(fptr);
2689  err+= add_name_string(fptr, part_elem->partition_name);
2690  if (show_partition_options)
2691  err+= add_partition_options(fptr, part_elem);
2692  if (j != (num_subparts-1))
2693  {
2694  err+= add_comma(fptr);
2695  err+= add_string(fptr, "\n");
2696  err+= add_space(fptr);
2697  err+= add_space(fptr);
2698  }
2699  else
2700  err+= add_end_parenthesis(fptr);
2701  } while (++j < num_subparts);
2702  }
2703  }
2704  if (i == (tot_num_parts-1))
2705  err+= add_end_parenthesis(fptr);
2706  } while (++i < tot_num_parts);
2707  }
2708  if (err)
2709  goto close_file;
2710  buffer_length= mysql_file_seek(fptr, 0L, MY_SEEK_END, MYF(0));
2711  if (unlikely(buffer_length == MY_FILEPOS_ERROR))
2712  goto close_file;
2713  if (unlikely(mysql_file_seek(fptr, 0L, MY_SEEK_SET, MYF(0))
2714  == MY_FILEPOS_ERROR))
2715  goto close_file;
2716  *buf_length= (uint)buffer_length;
2717  if (use_sql_alloc)
2718  buf= (char*) sql_alloc(*buf_length+1);
2719  else
2720  buf= (char*) my_malloc(*buf_length+1, MYF(MY_WME));
2721  if (!buf)
2722  goto close_file;
2723 
2724  if (unlikely(mysql_file_read(fptr, (uchar*)buf, *buf_length, MYF(MY_FNABP))))
2725  {
2726  if (!use_sql_alloc)
2727  my_free(buf);
2728  else
2729  buf= NULL;
2730  }
2731  else
2732  buf[*buf_length]= 0;
2733 
2734 close_file:
2735  mysql_file_close(fptr, MYF(0));
2736  DBUG_RETURN(buf);
2737 }
2738 
2739 
2740 /*
2741  Check if partition key fields are modified and if it can be handled by the
2742  underlying storage engine.
2743 
2744  SYNOPSIS
2745  partition_key_modified
2746  table TABLE object for which partition fields are set-up
2747  fields Bitmap representing fields to be modified
2748 
2749  RETURN VALUES
2750  TRUE Need special handling of UPDATE
2751  FALSE Normal UPDATE handling is ok
2752 */
2753 
2754 bool partition_key_modified(TABLE *table, const MY_BITMAP *fields)
2755 {
2756  Field **fld;
2757  partition_info *part_info= table->part_info;
2758  DBUG_ENTER("partition_key_modified");
2759 
2760  if (!part_info)
2761  DBUG_RETURN(FALSE);
2762  if (table->s->db_type()->partition_flags &&
2763  (table->s->db_type()->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY))
2764  DBUG_RETURN(FALSE);
2765  for (fld= part_info->full_part_field_array; *fld; fld++)
2766  if (bitmap_is_set(fields, (*fld)->field_index))
2767  DBUG_RETURN(TRUE);
2768  DBUG_RETURN(FALSE);
2769 }
2770 
2771 
2772 /*
2773  A function to handle correct handling of NULL values in partition
2774  functions.
2775  SYNOPSIS
2776  part_val_int()
2777  item_expr The item expression to evaluate
2778  out:result The value of the partition function,
2779  LONGLONG_MIN if any null value in function
2780  RETURN VALUES
2781  TRUE Error in val_int()
2782  FALSE ok
2783 */
2784 
2785 static inline int part_val_int(Item *item_expr, longlong *result)
2786 {
2787  *result= item_expr->val_int();
2788  if (item_expr->null_value)
2789  {
2790  if (current_thd->is_error())
2791  return TRUE;
2792  else
2793  *result= LONGLONG_MIN;
2794  }
2795  return FALSE;
2796 }
2797 
2798 
2799 /*
2800  The next set of functions are used to calculate the partition identity.
2801  A handler sets up a variable that corresponds to one of these functions
2802  to be able to quickly call it whenever the partition id needs to calculated
2803  based on the record in table->record[0] (or set up to fake that).
2804  There are 4 functions for hash partitioning and 2 for RANGE/LIST partitions.
2805  In addition there are 4 variants for RANGE subpartitioning and 4 variants
2806  for LIST subpartitioning thus in total there are 14 variants of this
2807  function.
2808 
2809  We have a set of support functions for these 14 variants. There are 4
2810  variants of hash functions and there is a function for each. The KEY
2811  partitioning uses the function calculate_key_hash_value to calculate the hash
2812  value based on an array of fields. The linear hash variants uses the
2813  method get_part_id_from_linear_hash to get the partition id using the
2814  hash value and some parameters calculated from the number of partitions.
2815 */
2816 
2817 /*
2818  A simple support function to calculate part_id given local part and
2819  sub part.
2820 
2821  SYNOPSIS
2822  get_part_id_for_sub()
2823  loc_part_id Local partition id
2824  sub_part_id Subpartition id
2825  num_subparts Number of subparts
2826 */
2827 
2828 inline
2829 static uint32 get_part_id_for_sub(uint32 loc_part_id, uint32 sub_part_id,
2830  uint num_subparts)
2831 {
2832  return (uint32)((loc_part_id * num_subparts) + sub_part_id);
2833 }
2834 
2835 
2836 /*
2837  Calculate part_id for (SUB)PARTITION BY HASH
2838 
2839  SYNOPSIS
2840  get_part_id_hash()
2841  num_parts Number of hash partitions
2842  part_expr Item tree of hash function
2843  out:part_id The returned partition id
2844  out:func_value Value of hash function
2845 
2846  RETURN VALUE
2847  != 0 Error code
2848  FALSE Success
2849 */
2850 
2851 static int get_part_id_hash(uint num_parts,
2852  Item *part_expr,
2853  uint32 *part_id,
2854  longlong *func_value)
2855 {
2856  longlong int_hash_id;
2857  DBUG_ENTER("get_part_id_hash");
2858 
2859  if (part_val_int(part_expr, func_value))
2860  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
2861 
2862  int_hash_id= *func_value % num_parts;
2863 
2864  *part_id= int_hash_id < 0 ? (uint32) -int_hash_id : (uint32) int_hash_id;
2865  DBUG_RETURN(FALSE);
2866 }
2867 
2868 
2869 /*
2870  Calculate part_id for (SUB)PARTITION BY LINEAR HASH
2871 
2872  SYNOPSIS
2873  get_part_id_linear_hash()
2874  part_info A reference to the partition_info struct where all the
2875  desired information is given
2876  num_parts Number of hash partitions
2877  part_expr Item tree of hash function
2878  out:part_id The returned partition id
2879  out:func_value Value of hash function
2880 
2881  RETURN VALUE
2882  != 0 Error code
2883  0 OK
2884 */
2885 
2886 static int get_part_id_linear_hash(partition_info *part_info,
2887  uint num_parts,
2888  Item *part_expr,
2889  uint32 *part_id,
2890  longlong *func_value)
2891 {
2892  DBUG_ENTER("get_part_id_linear_hash");
2893 
2894  if (part_val_int(part_expr, func_value))
2895  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
2896 
2897  *part_id= get_part_id_from_linear_hash(*func_value,
2898  part_info->linear_hash_mask,
2899  num_parts);
2900  DBUG_RETURN(FALSE);
2901 }
2902 
2903 
2915 inline
2916 static uint32 get_part_id_key(handler *file,
2917  Field **field_array,
2918  uint num_parts,
2919  longlong *func_value)
2920 {
2921  DBUG_ENTER("get_part_id_key");
2922  *func_value= file->calculate_key_hash_value(field_array);
2923  DBUG_RETURN((uint32) (*func_value % num_parts));
2924 }
2925 
2926 
2927 /*
2928  Calculate part_id for (SUB)PARTITION BY LINEAR KEY
2929 
2930  SYNOPSIS
2931  get_part_id_linear_key()
2932  part_info A reference to the partition_info struct where all the
2933  desired information is given
2934  field_array Array of fields for PARTTION KEY
2935  num_parts Number of KEY partitions
2936 
2937  RETURN VALUE
2938  Calculated partition id
2939 */
2940 
2941 inline
2942 static uint32 get_part_id_linear_key(partition_info *part_info,
2943  Field **field_array,
2944  uint num_parts,
2945  longlong *func_value)
2946 {
2947  DBUG_ENTER("get_part_id_linear_key");
2948 
2949  *func_value= part_info->table->file->calculate_key_hash_value(field_array);
2950  DBUG_RETURN(get_part_id_from_linear_hash(*func_value,
2951  part_info->linear_hash_mask,
2952  num_parts));
2953 }
2954 
2955 /*
2956  Copy to field buffers and set up field pointers
2957 
2958  SYNOPSIS
2959  copy_to_part_field_buffers()
2960  ptr Array of fields to copy
2961  field_bufs Array of field buffers to copy to
2962  restore_ptr Array of pointers to restore to
2963 
2964  RETURN VALUES
2965  NONE
2966  DESCRIPTION
2967  This routine is used to take the data from field pointer, convert
2968  it to a standard format and store this format in a field buffer
2969  allocated for this purpose. Next the field pointers are moved to
2970  point to the field buffers. There is a separate to restore the
2971  field pointers after this call.
2972 */
2973 
2974 static void copy_to_part_field_buffers(Field **ptr,
2975  uchar **field_bufs,
2976  uchar **restore_ptr)
2977 {
2978  Field *field;
2979  while ((field= *(ptr++)))
2980  {
2981  *restore_ptr= field->ptr;
2982  restore_ptr++;
2983  if (!field->maybe_null() || !field->is_null())
2984  {
2985  const CHARSET_INFO *cs= field->charset();
2986  uint max_len= field->pack_length();
2987  uint data_len= field->data_length();
2988  uchar *field_buf= *field_bufs;
2989  /*
2990  We only use the field buffer for VARCHAR and CHAR strings
2991  which isn't of a binary collation. We also only use the
2992  field buffer for fields which are not currently NULL.
2993  The field buffer will store a normalised string. We use
2994  the strnxfrm method to normalise the string.
2995  */
2996  if (field->type() == MYSQL_TYPE_VARCHAR)
2997  {
2998  uint len_bytes= ((Field_varstring*)field)->length_bytes;
2999  my_strnxfrm(cs, field_buf + len_bytes, max_len,
3000  field->ptr + len_bytes, data_len);
3001  if (len_bytes == 1)
3002  *field_buf= (uchar) data_len;
3003  else
3004  int2store(field_buf, data_len);
3005  }
3006  else
3007  {
3008  my_strnxfrm(cs, field_buf, max_len,
3009  field->ptr, max_len);
3010  }
3011  field->ptr= field_buf;
3012  }
3013  field_bufs++;
3014  }
3015  return;
3016 }
3017 
3018 /*
3019  Restore field pointers
3020  SYNOPSIS
3021  restore_part_field_pointers()
3022  ptr Array of fields to restore
3023  restore_ptr Array of field pointers to restore to
3024 
3025  RETURN VALUES
3026 */
3027 
3028 static void restore_part_field_pointers(Field **ptr, uchar **restore_ptr)
3029 {
3030  Field *field;
3031  while ((field= *(ptr++)))
3032  {
3033  field->ptr= *restore_ptr;
3034  restore_ptr++;
3035  }
3036  return;
3037 }
3038 
3039 /*
3040  This function is used to calculate the partition id where all partition
3041  fields have been prepared to point to a record where the partition field
3042  values are bound.
3043 
3044  SYNOPSIS
3045  get_partition_id()
3046  part_info A reference to the partition_info struct where all the
3047  desired information is given
3048  out:part_id The partition id is returned through this pointer
3049  out:func_value Value of partition function (longlong)
3050 
3051  RETURN VALUE
3052  part_id Partition id of partition that would contain
3053  row with given values of PF-fields
3054  HA_ERR_NO_PARTITION_FOUND The fields of the partition function didn't
3055  fit into any partition and thus the values of
3056  the PF-fields are not allowed.
3057 
3058  DESCRIPTION
3059  A routine used from write_row, update_row and delete_row from any
3060  handler supporting partitioning. It is also a support routine for
3061  get_partition_set used to find the set of partitions needed to scan
3062  for a certain index scan or full table scan.
3063 
3064  It is actually 9 different variants of this function which are called
3065  through a function pointer.
3066 
3067  get_partition_id_list
3068  get_partition_id_list_col
3069  get_partition_id_range
3070  get_partition_id_range_col
3071  get_partition_id_hash_nosub
3072  get_partition_id_key_nosub
3073  get_partition_id_linear_hash_nosub
3074  get_partition_id_linear_key_nosub
3075  get_partition_id_with_sub
3076 */
3077 
3078 /*
3079  This function is used to calculate the main partition to use in the case of
3080  subpartitioning and we don't know enough to get the partition identity in
3081  total.
3082 
3083  SYNOPSIS
3084  get_part_partition_id()
3085  part_info A reference to the partition_info struct where all the
3086  desired information is given
3087  out:part_id The partition id is returned through this pointer
3088  out:func_value The value calculated by partition function
3089 
3090  RETURN VALUE
3091  HA_ERR_NO_PARTITION_FOUND The fields of the partition function didn't
3092  fit into any partition and thus the values of
3093  the PF-fields are not allowed.
3094  0 OK
3095 
3096  DESCRIPTION
3097 
3098  It is actually 8 different variants of this function which are called
3099  through a function pointer.
3100 
3101  get_partition_id_list
3102  get_partition_id_list_col
3103  get_partition_id_range
3104  get_partition_id_range_col
3105  get_partition_id_hash_nosub
3106  get_partition_id_key_nosub
3107  get_partition_id_linear_hash_nosub
3108  get_partition_id_linear_key_nosub
3109 */
3110 
3111 static int get_part_id_charset_func_part(partition_info *part_info,
3112  uint32 *part_id,
3113  longlong *func_value)
3114 {
3115  int res;
3116  DBUG_ENTER("get_part_id_charset_func_part");
3117 
3118  copy_to_part_field_buffers(part_info->part_charset_field_array,
3119  part_info->part_field_buffers,
3120  part_info->restore_part_field_ptrs);
3121  res= part_info->get_part_partition_id_charset(part_info,
3122  part_id, func_value);
3123  restore_part_field_pointers(part_info->part_charset_field_array,
3124  part_info->restore_part_field_ptrs);
3125  DBUG_RETURN(res);
3126 }
3127 
3128 
3129 static int get_part_id_charset_func_subpart(partition_info *part_info,
3130  uint32 *part_id)
3131 {
3132  int res;
3133  DBUG_ENTER("get_part_id_charset_func_subpart");
3134 
3135  copy_to_part_field_buffers(part_info->subpart_charset_field_array,
3136  part_info->subpart_field_buffers,
3137  part_info->restore_subpart_field_ptrs);
3138  res= part_info->get_subpartition_id_charset(part_info, part_id);
3139  restore_part_field_pointers(part_info->subpart_charset_field_array,
3140  part_info->restore_subpart_field_ptrs);
3141  DBUG_RETURN(res);
3142 }
3143 
3144 int get_partition_id_list_col(partition_info *part_info,
3145  uint32 *part_id,
3146  longlong *func_value)
3147 {
3148  part_column_list_val *list_col_array= part_info->list_col_array;
3149  uint num_columns= part_info->part_field_list.elements;
3150  int list_index, cmp;
3151  int min_list_index= 0;
3152  int max_list_index= part_info->num_list_values - 1;
3153  DBUG_ENTER("get_partition_id_list_col");
3154 
3155  while (max_list_index >= min_list_index)
3156  {
3157  list_index= (max_list_index + min_list_index) >> 1;
3158  cmp= cmp_rec_and_tuple(list_col_array + list_index*num_columns,
3159  num_columns);
3160  if (cmp > 0)
3161  min_list_index= list_index + 1;
3162  else if (cmp < 0)
3163  {
3164  if (!list_index)
3165  goto notfound;
3166  max_list_index= list_index - 1;
3167  }
3168  else
3169  {
3170  *part_id= (uint32)list_col_array[list_index*num_columns].partition_id;
3171  DBUG_RETURN(0);
3172  }
3173  }
3174 notfound:
3175  *part_id= 0;
3176  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
3177 }
3178 
3179 
3180 int get_partition_id_list(partition_info *part_info,
3181  uint32 *part_id,
3182  longlong *func_value)
3183 {
3184  LIST_PART_ENTRY *list_array= part_info->list_array;
3185  int list_index;
3186  int min_list_index= 0;
3187  int max_list_index= part_info->num_list_values - 1;
3188  longlong part_func_value;
3189  int error= part_val_int(part_info->part_expr, &part_func_value);
3190  longlong list_value;
3191  bool unsigned_flag= part_info->part_expr->unsigned_flag;
3192  DBUG_ENTER("get_partition_id_list");
3193 
3194  if (error)
3195  goto notfound;
3196 
3197  if (part_info->part_expr->null_value)
3198  {
3199  if (part_info->has_null_value)
3200  {
3201  *part_id= part_info->has_null_part_id;
3202  DBUG_RETURN(0);
3203  }
3204  goto notfound;
3205  }
3206  *func_value= part_func_value;
3207  if (unsigned_flag)
3208  part_func_value-= 0x8000000000000000ULL;
3209  while (max_list_index >= min_list_index)
3210  {
3211  list_index= (max_list_index + min_list_index) >> 1;
3212  list_value= list_array[list_index].list_value;
3213  if (list_value < part_func_value)
3214  min_list_index= list_index + 1;
3215  else if (list_value > part_func_value)
3216  {
3217  if (!list_index)
3218  goto notfound;
3219  max_list_index= list_index - 1;
3220  }
3221  else
3222  {
3223  *part_id= (uint32)list_array[list_index].partition_id;
3224  DBUG_RETURN(0);
3225  }
3226  }
3227 notfound:
3228  *part_id= 0;
3229  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
3230 }
3231 
3232 
3233 uint32 get_partition_id_cols_list_for_endpoint(partition_info *part_info,
3234  bool left_endpoint,
3235  bool include_endpoint,
3236  uint32 nparts)
3237 {
3238  part_column_list_val *list_col_array= part_info->list_col_array;
3239  uint num_columns= part_info->part_field_list.elements;
3240  uint list_index;
3241  uint min_list_index= 0;
3242  uint max_list_index= part_info->num_list_values;
3243  DBUG_ENTER("get_partition_id_cols_list_for_endpoint");
3244 
3245  /* Find the matching partition (including taking endpoint into account). */
3246  do
3247  {
3248  /* Midpoint, adjusted down, so it can never be > last index. */
3249  list_index= (max_list_index + min_list_index) >> 1;
3250  if (cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
3251  nparts, left_endpoint, include_endpoint) > 0)
3252  min_list_index= list_index + 1;
3253  else
3254  max_list_index= list_index;
3255  } while (max_list_index > min_list_index);
3256  list_index= max_list_index;
3257 
3258  /* Given value must be LESS THAN or EQUAL to the found partition. */
3259  DBUG_ASSERT(list_index == part_info->num_list_values ||
3260  (0 >= cmp_rec_and_tuple_prune(list_col_array +
3261  list_index*num_columns,
3262  nparts, left_endpoint,
3263  include_endpoint)));
3264  /* Given value must be GREATER THAN the previous partition. */
3265  DBUG_ASSERT(list_index == 0 ||
3266  (0 < cmp_rec_and_tuple_prune(list_col_array +
3267  (list_index - 1)*num_columns,
3268  nparts, left_endpoint,
3269  include_endpoint)));
3270 
3271  if (!left_endpoint)
3272  {
3273  /* Set the end after this list tuple if not already after the last. */
3274  if (list_index < part_info->num_parts)
3275  list_index++;
3276  }
3277 
3278  DBUG_RETURN(list_index);
3279 }
3280 
3281 
3315 uint32 get_list_array_idx_for_endpoint_charset(partition_info *part_info,
3316  bool left_endpoint,
3317  bool include_endpoint)
3318 {
3319  uint32 res;
3320  copy_to_part_field_buffers(part_info->part_field_array,
3321  part_info->part_field_buffers,
3322  part_info->restore_part_field_ptrs);
3323  res= get_list_array_idx_for_endpoint(part_info, left_endpoint,
3324  include_endpoint);
3325  restore_part_field_pointers(part_info->part_field_array,
3326  part_info->restore_part_field_ptrs);
3327  return res;
3328 }
3329 
3330 uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
3331  bool left_endpoint,
3332  bool include_endpoint)
3333 {
3334  LIST_PART_ENTRY *list_array= part_info->list_array;
3335  uint list_index;
3336  uint min_list_index= 0, max_list_index= part_info->num_list_values - 1;
3337  longlong list_value;
3338  /* Get the partitioning function value for the endpoint */
3339  longlong part_func_value=
3340  part_info->part_expr->val_int_endpoint(left_endpoint, &include_endpoint);
3341  bool unsigned_flag= part_info->part_expr->unsigned_flag;
3342  DBUG_ENTER("get_list_array_idx_for_endpoint");
3343 
3344  if (part_info->part_expr->null_value)
3345  {
3346  /*
3347  Special handling for MONOTONIC functions that can return NULL for
3348  values that are comparable. I.e.
3349  '2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00')
3350  returns NULL which cannot be compared used <, >, <=, >= etc.
3351 
3352  Otherwise, just return the the first index (lowest value).
3353  */
3354  enum_monotonicity_info monotonic;
3355  monotonic= part_info->part_expr->get_monotonicity_info();
3356  if (monotonic != MONOTONIC_INCREASING_NOT_NULL &&
3357  monotonic != MONOTONIC_STRICT_INCREASING_NOT_NULL)
3358  {
3359  /* F(col) can not return NULL, return index with lowest value */
3360  DBUG_RETURN(0);
3361  }
3362  }
3363 
3364  if (unsigned_flag)
3365  part_func_value-= 0x8000000000000000ULL;
3366  DBUG_ASSERT(part_info->num_list_values);
3367  do
3368  {
3369  list_index= (max_list_index + min_list_index) >> 1;
3370  list_value= list_array[list_index].list_value;
3371  if (list_value < part_func_value)
3372  min_list_index= list_index + 1;
3373  else if (list_value > part_func_value)
3374  {
3375  if (!list_index)
3376  goto notfound;
3377  max_list_index= list_index - 1;
3378  }
3379  else
3380  {
3381  DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint));
3382  }
3383  } while (max_list_index >= min_list_index);
3384 notfound:
3385  if (list_value < part_func_value)
3386  list_index++;
3387  DBUG_RETURN(list_index);
3388 }
3389 
3390 
3391 int get_partition_id_range_col(partition_info *part_info,
3392  uint32 *part_id,
3393  longlong *func_value)
3394 {
3395  part_column_list_val *range_col_array= part_info->range_col_array;
3396  uint num_columns= part_info->part_field_list.elements;
3397  uint max_partition= part_info->num_parts - 1;
3398  uint min_part_id= 0;
3399  uint max_part_id= max_partition;
3400  uint loc_part_id;
3401  DBUG_ENTER("get_partition_id_range_col");
3402 
3403  while (max_part_id > min_part_id)
3404  {
3405  loc_part_id= (max_part_id + min_part_id + 1) >> 1;
3406  if (cmp_rec_and_tuple(range_col_array + loc_part_id*num_columns,
3407  num_columns) >= 0)
3408  min_part_id= loc_part_id + 1;
3409  else
3410  max_part_id= loc_part_id - 1;
3411  }
3412  loc_part_id= max_part_id;
3413  if (loc_part_id != max_partition)
3414  if (cmp_rec_and_tuple(range_col_array + loc_part_id*num_columns,
3415  num_columns) >= 0)
3416  loc_part_id++;
3417  *part_id= (uint32)loc_part_id;
3418  if (loc_part_id == max_partition &&
3419  (cmp_rec_and_tuple(range_col_array + loc_part_id*num_columns,
3420  num_columns) >= 0))
3421  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
3422 
3423  DBUG_PRINT("exit",("partition: %d", *part_id));
3424  DBUG_RETURN(0);
3425 }
3426 
3427 
3428 int get_partition_id_range(partition_info *part_info,
3429  uint32 *part_id,
3430  longlong *func_value)
3431 {
3432  longlong *range_array= part_info->range_int_array;
3433  uint max_partition= part_info->num_parts - 1;
3434  uint min_part_id= 0;
3435  uint max_part_id= max_partition;
3436  uint loc_part_id;
3437  longlong part_func_value;
3438  int error= part_val_int(part_info->part_expr, &part_func_value);
3439  bool unsigned_flag= part_info->part_expr->unsigned_flag;
3440  DBUG_ENTER("get_partition_id_range");
3441 
3442  if (error)
3443  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
3444 
3445  if (part_info->part_expr->null_value)
3446  {
3447  *part_id= 0;
3448  DBUG_RETURN(0);
3449  }
3450  *func_value= part_func_value;
3451  if (unsigned_flag)
3452  part_func_value-= 0x8000000000000000ULL;
3453  /* Search for the partition containing part_func_value */
3454  while (max_part_id > min_part_id)
3455  {
3456  loc_part_id= (max_part_id + min_part_id) / 2;
3457  if (range_array[loc_part_id] <= part_func_value)
3458  min_part_id= loc_part_id + 1;
3459  else
3460  max_part_id= loc_part_id;
3461  }
3462  loc_part_id= max_part_id;
3463  *part_id= (uint32)loc_part_id;
3464  if (loc_part_id == max_partition &&
3465  part_func_value >= range_array[loc_part_id] &&
3466  !part_info->defined_max_value)
3467  DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
3468 
3469  DBUG_PRINT("exit",("partition: %d", *part_id));
3470  DBUG_RETURN(0);
3471 }
3472 
3473 
3474 /*
3475  Find the sub-array of part_info->range_int_array that covers given interval
3476 
3477  SYNOPSIS
3478  get_partition_id_range_for_endpoint()
3479  part_info Partitioning info (partitioning type must be RANGE)
3480  left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
3481  FALSE - the interval is (-inf; a] or (-inf; a).
3482  include_endpoint TRUE <=> the endpoint itself is included in the
3483  interval
3484 
3485  DESCRIPTION
3486  This function finds the sub-array of part_info->range_int_array where the
3487  elements have non-empty intersections with the given interval.
3488 
3489  A range_int_array element at index idx represents the interval
3490 
3491  [range_int_array[idx-1], range_int_array[idx]),
3492 
3493  intervals are disjoint and ordered by their right bound, so
3494 
3495  1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
3496  sought sub-array starts at some index idx and continues till array end.
3497  The function returns first number idx, such that the interval
3498  represented by range_int_array[idx] has non empty intersection with
3499  the passed interval.
3500 
3501  2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
3502  sought sub-array starts at array start and continues till some last
3503  index idx.
3504  The function returns first number idx, such that the interval
3505  represented by range_int_array[idx] has EMPTY intersection with the
3506  passed interval.
3507  If the interval represented by the last array element has non-empty
3508  intersection with the passed interval, part_info->num_parts is
3509  returned.
3510 
3511  RETURN
3512  The edge of corresponding part_info->range_int_array sub-array.
3513 */
3514 
3515 static uint32
3516 get_partition_id_range_for_endpoint_charset(partition_info *part_info,
3517  bool left_endpoint,
3518  bool include_endpoint)
3519 {
3520  uint32 res;
3521  copy_to_part_field_buffers(part_info->part_field_array,
3522  part_info->part_field_buffers,
3523  part_info->restore_part_field_ptrs);
3524  res= get_partition_id_range_for_endpoint(part_info, left_endpoint,
3525  include_endpoint);
3526  restore_part_field_pointers(part_info->part_field_array,
3527  part_info->restore_part_field_ptrs);
3528  return res;
3529 }
3530 
3531 uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
3532  bool left_endpoint,
3533  bool include_endpoint)
3534 {
3535  longlong *range_array= part_info->range_int_array;
3536  longlong part_end_val;
3537  uint max_partition= part_info->num_parts - 1;
3538  uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
3539  /* Get the partitioning function value for the endpoint */
3540  longlong part_func_value=
3541  part_info->part_expr->val_int_endpoint(left_endpoint, &include_endpoint);
3542 
3543  bool unsigned_flag= part_info->part_expr->unsigned_flag;
3544  DBUG_ENTER("get_partition_id_range_for_endpoint");
3545 
3546  if (part_info->part_expr->null_value)
3547  {
3548  /*
3549  Special handling for MONOTONIC functions that can return NULL for
3550  values that are comparable. I.e.
3551  '2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00')
3552  returns NULL which cannot be compared used <, >, <=, >= etc.
3553 
3554  Otherwise, just return the first partition
3555  (may be included if not left endpoint)
3556  */
3557  enum_monotonicity_info monotonic;
3558  monotonic= part_info->part_expr->get_monotonicity_info();
3559  if (monotonic != MONOTONIC_INCREASING_NOT_NULL &&
3560  monotonic != MONOTONIC_STRICT_INCREASING_NOT_NULL)
3561  {
3562  /* F(col) can not return NULL, return partition with lowest value */
3563  if (!left_endpoint && include_endpoint)
3564  DBUG_RETURN(1);
3565  DBUG_RETURN(0);
3566 
3567  }
3568  }
3569 
3570  if (unsigned_flag)
3571  part_func_value-= 0x8000000000000000ULL;
3572  if (left_endpoint && !include_endpoint)
3573  part_func_value++;
3574 
3575  /*
3576  Search for the partition containing part_func_value
3577  (including the right endpoint).
3578  */
3579  while (max_part_id > min_part_id)
3580  {
3581  loc_part_id= (max_part_id + min_part_id) / 2;
3582  if (range_array[loc_part_id] < part_func_value)
3583  min_part_id= loc_part_id + 1;
3584  else
3585  max_part_id= loc_part_id;
3586  }
3587  loc_part_id= max_part_id;
3588 
3589  /* Adjust for endpoints */
3590  part_end_val= range_array[loc_part_id];
3591  if (left_endpoint)
3592  {
3593  DBUG_ASSERT(part_func_value > part_end_val ?
3594  (loc_part_id == max_partition &&
3595  !part_info->defined_max_value) :
3596  1);
3597  /*
3598  In case of PARTITION p VALUES LESS THAN MAXVALUE
3599  the maximum value is in the current (last) partition.
3600  If value is equal or greater than the endpoint,
3601  the range starts from the next partition.
3602  */
3603  if (part_func_value >= part_end_val &&
3604  (loc_part_id < max_partition || !part_info->defined_max_value))
3605  loc_part_id++;
3606  }
3607  else
3608  {
3609  /* if 'WHERE <= X' and partition is LESS THAN (X) include next partition */
3610  if (include_endpoint && loc_part_id < max_partition &&
3611  part_func_value == part_end_val)
3612  loc_part_id++;
3613 
3614  /* Right endpoint, set end after correct partition */
3615  loc_part_id++;
3616  }
3617  DBUG_RETURN(loc_part_id);
3618 }
3619 
3620 
3621 int get_partition_id_hash_nosub(partition_info *part_info,
3622  uint32 *part_id,
3623  longlong *func_value)
3624 {
3625  return get_part_id_hash(part_info->num_parts, part_info->part_expr,
3626  part_id, func_value);
3627 }
3628 
3629 
3630 int get_partition_id_linear_hash_nosub(partition_info *part_info,
3631  uint32 *part_id,
3632  longlong *func_value)
3633 {
3634  return get_part_id_linear_hash(part_info, part_info->num_parts,
3635  part_info->part_expr, part_id, func_value);
3636 }
3637 
3638 
3639 int get_partition_id_key_nosub(partition_info *part_info,
3640  uint32 *part_id,
3641  longlong *func_value)
3642 {
3643  *part_id= get_part_id_key(part_info->table->file,
3644  part_info->part_field_array,
3645  part_info->num_parts, func_value);
3646  return 0;
3647 }
3648 
3649 
3650 int get_partition_id_linear_key_nosub(partition_info *part_info,
3651  uint32 *part_id,
3652  longlong *func_value)
3653 {
3654  *part_id= get_part_id_linear_key(part_info,
3655  part_info->part_field_array,
3656  part_info->num_parts, func_value);
3657  return 0;
3658 }
3659 
3660 
3661 int get_partition_id_with_sub(partition_info *part_info,
3662  uint32 *part_id,
3663  longlong *func_value)
3664 {
3665  uint32 loc_part_id, sub_part_id;
3666  uint num_subparts;
3667  int error;
3668  DBUG_ENTER("get_partition_id_with_sub");
3669 
3670  if (unlikely((error= part_info->get_part_partition_id(part_info,
3671  &loc_part_id,
3672  func_value))))
3673  {
3674  DBUG_RETURN(error);
3675  }
3676  num_subparts= part_info->num_subparts;
3677  if (unlikely((error= part_info->get_subpartition_id(part_info,
3678  &sub_part_id))))
3679  {
3680  DBUG_RETURN(error);
3681  }
3682  *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, num_subparts);
3683  DBUG_RETURN(0);
3684 }
3685 
3686 
3687 /*
3688  This function is used to calculate the subpartition id
3689 
3690  SYNOPSIS
3691  get_subpartition_id()
3692  part_info A reference to the partition_info struct where all the
3693  desired information is given
3694 
3695  RETURN VALUE
3696  part_id The subpartition identity
3697 
3698  DESCRIPTION
3699  A routine used in some SELECT's when only partial knowledge of the
3700  partitions is known.
3701 
3702  It is actually 4 different variants of this function which are called
3703  through a function pointer.
3704 
3705  get_partition_id_hash_sub
3706  get_partition_id_key_sub
3707  get_partition_id_linear_hash_sub
3708  get_partition_id_linear_key_sub
3709 */
3710 
3711 int get_partition_id_hash_sub(partition_info *part_info,
3712  uint32 *part_id)
3713 {
3714  longlong func_value;
3715  return get_part_id_hash(part_info->num_subparts, part_info->subpart_expr,
3716  part_id, &func_value);
3717 }
3718 
3719 
3720 int get_partition_id_linear_hash_sub(partition_info *part_info,
3721  uint32 *part_id)
3722 {
3723  longlong func_value;
3724  return get_part_id_linear_hash(part_info, part_info->num_subparts,
3725  part_info->subpart_expr, part_id,
3726  &func_value);
3727 }
3728 
3729 
3730 int get_partition_id_key_sub(partition_info *part_info,
3731  uint32 *part_id)
3732 {
3733  longlong func_value;
3734  *part_id= get_part_id_key(part_info->table->file,
3735  part_info->subpart_field_array,
3736  part_info->num_subparts, &func_value);
3737  return FALSE;
3738 }
3739 
3740 
3741 int get_partition_id_linear_key_sub(partition_info *part_info,
3742  uint32 *part_id)
3743 {
3744  longlong func_value;
3745  *part_id= get_part_id_linear_key(part_info,
3746  part_info->subpart_field_array,
3747  part_info->num_subparts, &func_value);
3748  return FALSE;
3749 }
3750 
3751 
3752 /*
3753  Set an indicator on all partition fields that are set by the key
3754 
3755  SYNOPSIS
3756  set_PF_fields_in_key()
3757  key_info Information about the index
3758  key_length Length of key
3759 
3760  RETURN VALUE
3761  TRUE Found partition field set by key
3762  FALSE No partition field set by key
3763 */
3764 
3765 static bool set_PF_fields_in_key(KEY *key_info, uint key_length)
3766 {
3767  KEY_PART_INFO *key_part;
3768  bool found_part_field= FALSE;
3769  DBUG_ENTER("set_PF_fields_in_key");
3770 
3771  for (key_part= key_info->key_part; (int)key_length > 0; key_part++)
3772  {
3773  if (key_part->null_bit)
3774  key_length--;
3775  if (key_part->type == HA_KEYTYPE_BIT)
3776  {
3777  if (((Field_bit*)key_part->field)->bit_len)
3778  key_length--;
3779  }
3780  if (key_part->key_part_flag & (HA_BLOB_PART + HA_VAR_LENGTH_PART))
3781  {
3782  key_length-= HA_KEY_BLOB_LENGTH;
3783  }
3784  if (key_length < key_part->length)
3785  break;
3786  key_length-= key_part->length;
3787  if (key_part->field->flags & FIELD_IN_PART_FUNC_FLAG)
3788  {
3789  found_part_field= TRUE;
3790  key_part->field->flags|= GET_FIXED_FIELDS_FLAG;
3791  }
3792  }
3793  DBUG_RETURN(found_part_field);
3794 }
3795 
3796 
3797 /*
3798  We have found that at least one partition field was set by a key, now
3799  check if a partition function has all its fields bound or not.
3800 
3801  SYNOPSIS
3802  check_part_func_bound()
3803  ptr Array of fields NULL terminated (partition fields)
3804 
3805  RETURN VALUE
3806  TRUE All fields in partition function are set
3807  FALSE Not all fields in partition function are set
3808 */
3809 
3810 static bool check_part_func_bound(Field **ptr)
3811 {
3812  bool result= TRUE;
3813  DBUG_ENTER("check_part_func_bound");
3814 
3815  for (; *ptr; ptr++)
3816  {
3817  if (!((*ptr)->flags & GET_FIXED_FIELDS_FLAG))
3818  {
3819  result= FALSE;
3820  break;
3821  }
3822  }
3823  DBUG_RETURN(result);
3824 }
3825 
3826 
3827 /*
3828  Get the id of the subpartitioning part by using the key buffer of the
3829  index scan.
3830 
3831  SYNOPSIS
3832  get_sub_part_id_from_key()
3833  table The table object
3834  buf A buffer that can be used to evaluate the partition function
3835  key_info The index object
3836  key_spec A key_range containing key and key length
3837  out:part_id The returned partition id
3838 
3839  RETURN VALUES
3840  TRUE All fields in partition function are set
3841  FALSE Not all fields in partition function are set
3842 
3843  DESCRIPTION
3844  Use key buffer to set-up record in buf, move field pointers and
3845  get the partition identity and restore field pointers afterwards.
3846 */
3847 
3848 static int get_sub_part_id_from_key(const TABLE *table,uchar *buf,
3849  KEY *key_info,
3850  const key_range *key_spec,
3851  uint32 *part_id)
3852 {
3853  uchar *rec0= table->record[0];
3854  partition_info *part_info= table->part_info;
3855  int res;
3856  DBUG_ENTER("get_sub_part_id_from_key");
3857 
3858  key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length);
3859  if (likely(rec0 == buf))
3860  {
3861  res= part_info->get_subpartition_id(part_info, part_id);
3862  }
3863  else
3864  {
3865  Field **part_field_array= part_info->subpart_field_array;
3866  set_field_ptr(part_field_array, buf, rec0);
3867  res= part_info->get_subpartition_id(part_info, part_id);
3868  set_field_ptr(part_field_array, rec0, buf);
3869  }
3870  DBUG_RETURN(res);
3871 }
3872 
3873 /*
3874  Get the id of the partitioning part by using the key buffer of the
3875  index scan.
3876 
3877  SYNOPSIS
3878  get_part_id_from_key()
3879  table The table object
3880  buf A buffer that can be used to evaluate the partition function
3881  key_info The index object
3882  key_spec A key_range containing key and key length
3883  out:part_id Partition to use
3884 
3885  RETURN VALUES
3886  TRUE Partition to use not found
3887  FALSE Ok, part_id indicates partition to use
3888 
3889  DESCRIPTION
3890  Use key buffer to set-up record in buf, move field pointers and
3891  get the partition identity and restore field pointers afterwards.
3892 */
3893 
3894 bool get_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info,
3895  const key_range *key_spec, uint32 *part_id)
3896 {
3897  bool result;
3898  uchar *rec0= table->record[0];
3899  partition_info *part_info= table->part_info;
3900  longlong func_value;
3901  DBUG_ENTER("get_part_id_from_key");
3902 
3903  key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length);
3904  if (likely(rec0 == buf))
3905  {
3906  result= part_info->get_part_partition_id(part_info, part_id,
3907  &func_value);
3908  }
3909  else
3910  {
3911  Field **part_field_array= part_info->part_field_array;
3912  set_field_ptr(part_field_array, buf, rec0);
3913  result= part_info->get_part_partition_id(part_info, part_id,
3914  &func_value);
3915  set_field_ptr(part_field_array, rec0, buf);
3916  }
3917  DBUG_RETURN(result);
3918 }
3919 
3920 /*
3921  Get the partitioning id of the full PF by using the key buffer of the
3922  index scan.
3923 
3924  SYNOPSIS
3925  get_full_part_id_from_key()
3926  table The table object
3927  buf A buffer that is used to evaluate the partition function
3928  key_info The index object
3929  key_spec A key_range containing key and key length
3930  out:part_spec A partition id containing start part and end part
3931 
3932  RETURN VALUES
3933  part_spec
3934  No partitions to scan is indicated by end_part > start_part when returning
3935 
3936  DESCRIPTION
3937  Use key buffer to set-up record in buf, move field pointers if needed and
3938  get the partition identity and restore field pointers afterwards.
3939 */
3940 
3941 void get_full_part_id_from_key(const TABLE *table, uchar *buf,
3942  KEY *key_info,
3943  const key_range *key_spec,
3944  part_id_range *part_spec)
3945 {
3946  bool result;
3947  partition_info *part_info= table->part_info;
3948  uchar *rec0= table->record[0];
3949  longlong func_value;
3950  DBUG_ENTER("get_full_part_id_from_key");
3951 
3952  key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length);
3953  if (likely(rec0 == buf))
3954  {
3955  result= part_info->get_partition_id(part_info, &part_spec->start_part,
3956  &func_value);
3957  }
3958  else
3959  {
3960  Field **part_field_array= part_info->full_part_field_array;
3961  set_field_ptr(part_field_array, buf, rec0);
3962  result= part_info->get_partition_id(part_info, &part_spec->start_part,
3963  &func_value);
3964  set_field_ptr(part_field_array, rec0, buf);
3965  }
3966  part_spec->end_part= part_spec->start_part;
3967  if (unlikely(result))
3968  part_spec->start_part++;
3969  DBUG_VOID_RETURN;
3970 }
3971 
3972 
3985 bool verify_data_with_partition(TABLE *table, TABLE *part_table,
3986  uint32 part_id)
3987 {
3988  uint32 found_part_id;
3989  longlong func_value; /* Unused */
3990  handler *file;
3991  int error;
3992  uchar *old_rec;
3993  partition_info *part_info;
3994  DBUG_ENTER("verify_data_with_partition");
3995  DBUG_ASSERT(table && table->file && part_table && part_table->part_info &&
3996  part_table->file);
3997 
3998  /*
3999  Verify all table rows.
4000  First implementation uses full scan + evaluates partition functions for
4001  every row. TODO: add optimization to use index if possible, see WL#5397.
4002 
4003  1) Open both tables (already done) and set the row buffers to use
4004  the same buffer (to avoid copy).
4005  2) Init rnd on table.
4006  3) loop over all rows.
4007  3.1) verify that partition_id on the row is correct. Break if error.
4008  */
4009  file= table->file;
4010  part_info= part_table->part_info;
4011  bitmap_union(table->read_set, &part_info->full_part_field_set);
4012  old_rec= part_table->record[0];
4013  part_table->record[0]= table->record[0];
4014  set_field_ptr(part_info->full_part_field_array, table->record[0], old_rec);
4015  if ((error= file->ha_rnd_init(TRUE)))
4016  {
4017  file->print_error(error, MYF(0));
4018  goto err;
4019  }
4020 
4021  do
4022  {
4023  if ((error= file->ha_rnd_next(table->record[0])))
4024  {
4025  if (error == HA_ERR_RECORD_DELETED)
4026  continue;
4027  if (error == HA_ERR_END_OF_FILE)
4028  error= 0;
4029  else
4030  file->print_error(error, MYF(0));
4031  break;
4032  }
4033  if ((error= part_info->get_partition_id(part_info, &found_part_id,
4034  &func_value)))
4035  {
4036  part_table->file->print_error(error, MYF(0));
4037  break;
4038  }
4039  DEBUG_SYNC(current_thd, "swap_partition_first_row_read");
4040  if (found_part_id != part_id)
4041  {
4042  my_error(ER_ROW_DOES_NOT_MATCH_PARTITION, MYF(0));
4043  error= 1;
4044  break;
4045  }
4046  } while (TRUE);
4047  (void) file->ha_rnd_end();
4048 err:
4049  set_field_ptr(part_info->full_part_field_array, old_rec,
4050  table->record[0]);
4051  part_table->record[0]= old_rec;
4052  if (error)
4053  DBUG_RETURN(TRUE);
4054  DBUG_RETURN(FALSE);
4055 }
4056 
4057 
4058 /*
4059  Prune the set of partitions to use in query
4060 
4061  SYNOPSIS
4062  prune_partition_set()
4063  table The table object
4064  out:part_spec Contains start part, end part
4065 
4066  DESCRIPTION
4067  This function is called to prune the range of partitions to scan by
4068  checking the read_partitions bitmap.
4069  If start_part > end_part at return it means no partition needs to be
4070  scanned. If start_part == end_part it always means a single partition
4071  needs to be scanned.
4072 
4073  RETURN VALUE
4074  part_spec
4075 */
4076 void prune_partition_set(const TABLE *table, part_id_range *part_spec)
4077 {
4078  int last_partition= -1;
4079  uint i;
4080  partition_info *part_info= table->part_info;
4081 
4082  DBUG_ENTER("prune_partition_set");
4083  for (i= part_spec->start_part; i <= part_spec->end_part; i++)
4084  {
4085  if (bitmap_is_set(&(part_info->read_partitions), i))
4086  {
4087  DBUG_PRINT("info", ("Partition %d is set", i));
4088  if (last_partition == -1)
4089  /* First partition found in set and pruned bitmap */
4090  part_spec->start_part= i;
4091  last_partition= i;
4092  }
4093  }
4094  if (last_partition == -1)
4095  /* No partition found in pruned bitmap */
4096  part_spec->start_part= part_spec->end_part + 1;
4097  else //if (last_partition != -1)
4098  part_spec->end_part= last_partition;
4099 
4100  DBUG_VOID_RETURN;
4101 }
4102 
4103 /*
4104  Get the set of partitions to use in query.
4105 
4106  SYNOPSIS
4107  get_partition_set()
4108  table The table object
4109  buf A buffer that can be used to evaluate the partition function
4110  index The index of the key used, if MAX_KEY no index used
4111  key_spec A key_range containing key and key length
4112  out:part_spec Contains start part, end part and indicator if bitmap is
4113  used for which partitions to scan
4114 
4115  DESCRIPTION
4116  This function is called to discover which partitions to use in an index
4117  scan or a full table scan.
4118  It returns a range of partitions to scan. If there are holes in this
4119  range with partitions that are not needed to scan a bit array is used
4120  to signal which partitions to use and which not to use.
4121  If start_part > end_part at return it means no partition needs to be
4122  scanned. If start_part == end_part it always means a single partition
4123  needs to be scanned.
4124 
4125  RETURN VALUE
4126  part_spec
4127 */
4128 void get_partition_set(const TABLE *table, uchar *buf, const uint index,
4129  const key_range *key_spec, part_id_range *part_spec)
4130 {
4131  partition_info *part_info= table->part_info;
4132  uint num_parts= part_info->get_tot_partitions();
4133  uint i, part_id;
4134  uint sub_part= num_parts;
4135  uint32 part_part= num_parts;
4136  KEY *key_info= NULL;
4137  bool found_part_field= FALSE;
4138  DBUG_ENTER("get_partition_set");
4139 
4140  part_spec->start_part= 0;
4141  part_spec->end_part= num_parts - 1;
4142  if ((index < MAX_KEY) &&
4143  key_spec && key_spec->flag == (uint)HA_READ_KEY_EXACT &&
4144  part_info->some_fields_in_PF.is_set(index))
4145  {
4146  key_info= table->key_info+index;
4147  /*
4148  The index can potentially provide at least one PF-field (field in the
4149  partition function). Thus it is interesting to continue our probe.
4150  */
4151  if (key_spec->length == key_info->key_length)
4152  {
4153  /*
4154  The entire key is set so we can check whether we can immediately
4155  derive either the complete PF or if we can derive either
4156  the top PF or the subpartitioning PF. This can be established by
4157  checking precalculated bits on each index.
4158  */
4159  if (part_info->all_fields_in_PF.is_set(index))
4160  {
4161  /*
4162  We can derive the exact partition to use, no more than this one
4163  is needed.
4164  */
4165  get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec);
4166  /*
4167  Check if range can be adjusted by looking in read_partitions
4168  */
4169  prune_partition_set(table, part_spec);
4170  DBUG_VOID_RETURN;
4171  }
4172  else if (part_info->is_sub_partitioned())
4173  {
4174  if (part_info->all_fields_in_SPF.is_set(index))
4175  {
4176  if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part))
4177  {
4178  part_spec->start_part= num_parts;
4179  DBUG_VOID_RETURN;
4180  }
4181  }
4182  else if (part_info->all_fields_in_PPF.is_set(index))
4183  {
4184  if (get_part_id_from_key(table,buf,key_info,
4185  key_spec,(uint32*)&part_part))
4186  {
4187  /*
4188  The value of the RANGE or LIST partitioning was outside of
4189  allowed values. Thus it is certain that the result of this
4190  scan will be empty.
4191  */
4192  part_spec->start_part= num_parts;
4193  DBUG_VOID_RETURN;
4194  }
4195  }
4196  }
4197  }
4198  else
4199  {
4200  /*
4201  Set an indicator on all partition fields that are bound.
4202  If at least one PF-field was bound it pays off to check whether
4203  the PF or PPF or SPF has been bound.
4204  (PF = Partition Function, SPF = Subpartition Function and
4205  PPF = Partition Function part of subpartitioning)
4206  */
4207  if ((found_part_field= set_PF_fields_in_key(key_info,
4208  key_spec->length)))
4209  {
4210  if (check_part_func_bound(part_info->full_part_field_array))
4211  {
4212  /*
4213  We were able to bind all fields in the partition function even
4214  by using only a part of the key. Calculate the partition to use.
4215  */
4216  get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec);
4217  clear_indicator_in_key_fields(key_info);
4218  /*
4219  Check if range can be adjusted by looking in read_partitions
4220  */
4221  prune_partition_set(table, part_spec);
4222  DBUG_VOID_RETURN;
4223  }
4224  else if (part_info->is_sub_partitioned())
4225  {
4226  if (check_part_func_bound(part_info->subpart_field_array))
4227  {
4228  if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part))
4229  {
4230  part_spec->start_part= num_parts;
4231  clear_indicator_in_key_fields(key_info);
4232  DBUG_VOID_RETURN;
4233  }
4234  }
4235  else if (check_part_func_bound(part_info->part_field_array))
4236  {
4237  if (get_part_id_from_key(table,buf,key_info,key_spec,&part_part))
4238  {
4239  part_spec->start_part= num_parts;
4240  clear_indicator_in_key_fields(key_info);
4241  DBUG_VOID_RETURN;
4242  }
4243  }
4244  }
4245  }
4246  }
4247  }
4248  {
4249  /*
4250  The next step is to analyse the table condition to see whether any
4251  information about which partitions to scan can be derived from there.
4252  Currently not implemented.
4253  */
4254  }
4255  /*
4256  If we come here we have found a range of sorts we have either discovered
4257  nothing or we have discovered a range of partitions with possible holes
4258  in it. We need a bitvector to further the work here.
4259  */
4260  if (!(part_part == num_parts && sub_part == num_parts))
4261  {
4262  /*
4263  We can only arrive here if we are using subpartitioning.
4264  */
4265  if (part_part != num_parts)
4266  {
4267  /*
4268  We know the top partition and need to scan all underlying
4269  subpartitions. This is a range without holes.
4270  */
4271  DBUG_ASSERT(sub_part == num_parts);
4272  part_spec->start_part= part_part * part_info->num_subparts;
4273  part_spec->end_part= part_spec->start_part+part_info->num_subparts - 1;
4274  }
4275  else
4276  {
4277  DBUG_ASSERT(sub_part != num_parts);
4278  part_spec->start_part= sub_part;
4279  part_spec->end_part=sub_part+
4280  (part_info->num_subparts*(part_info->num_parts-1));
4281  for (i= 0, part_id= sub_part; i < part_info->num_parts;
4282  i++, part_id+= part_info->num_subparts)
4283  ; //Set bit part_id in bit array
4284  }
4285  }
4286  if (found_part_field)
4287  clear_indicator_in_key_fields(key_info);
4288  /*
4289  Check if range can be adjusted by looking in read_partitions
4290  */
4291  prune_partition_set(table, part_spec);
4292  DBUG_VOID_RETURN;
4293 }
4294 
4295 /*
4296  If the table is partitioned we will read the partition info into the
4297  .frm file here.
4298  -------------------------------
4299  | Fileinfo 64 bytes |
4300  -------------------------------
4301  | Formnames 7 bytes |
4302  -------------------------------
4303  | Not used 4021 bytes |
4304  -------------------------------
4305  | Keyinfo + record |
4306  -------------------------------
4307  | Padded to next multiple |
4308  | of IO_SIZE |
4309  -------------------------------
4310  | Forminfo 288 bytes |
4311  -------------------------------
4312  | Screen buffer, to make |
4313  |field names readable |
4314  -------------------------------
4315  | Packed field info |
4316  |17 + 1 + strlen(field_name) |
4317  | + 1 end of file character |
4318  -------------------------------
4319  | Partition info |
4320  -------------------------------
4321  We provide the length of partition length in Fileinfo[55-58].
4322 
4323  Read the partition syntax from the frm file and parse it to get the
4324  data structures of the partitioning.
4325 
4326  SYNOPSIS
4327  mysql_unpack_partition()
4328  thd Thread object
4329  part_buf Partition info from frm file
4330  part_info_len Length of partition syntax
4331  table Table object of partitioned table
4332  create_table_ind Is it called from CREATE TABLE
4333  default_db_type What is the default engine of the table
4334  work_part_info_used Flag is raised if we don't create new
4335  part_info, but used thd->work_part_info
4336 
4337  RETURN VALUE
4338  TRUE Error
4339  FALSE Sucess
4340 
4341  DESCRIPTION
4342  Read the partition syntax from the current position in the frm file.
4343  Initiate a LEX object, save the list of item tree objects to free after
4344  the query is done. Set-up partition info object such that parser knows
4345  it is called from internally. Call parser to create data structures
4346  (best possible recreation of item trees and so forth since there is no
4347  serialisation of these objects other than in parseable text format).
4348  We need to save the text of the partition functions since it is not
4349  possible to retrace this given an item tree.
4350 */
4351 
4352 bool mysql_unpack_partition(THD *thd,
4353  char *part_buf, uint part_info_len,
4354  TABLE* table, bool is_create_table_ind,
4355  handlerton *default_db_type,
4356  bool *work_part_info_used)
4357 {
4358  bool result= TRUE;
4359  partition_info *part_info;
4360  const CHARSET_INFO *old_character_set_client=
4361  thd->variables.character_set_client;
4362  LEX *old_lex= thd->lex;
4363  LEX lex;
4364  PSI_statement_locker *parent_locker= thd->m_statement_psi;
4365  DBUG_ENTER("mysql_unpack_partition");
4366 
4367  thd->variables.character_set_client= system_charset_info;
4368 
4369  Parser_state parser_state;
4370  if (parser_state.init(thd, part_buf, part_info_len))
4371  goto end;
4372 
4373  if (init_lex_with_single_table(thd, table, &lex))
4374  goto end;
4375 
4376  /*
4377  All Items created is put into a free list on the THD object. This list
4378  is used to free all Item objects after completing a query. We don't
4379  want that to happen with the Item tree created as part of the partition
4380  info. This should be attached to the table object and remain so until
4381  the table object is released.
4382  Thus we move away the current list temporarily and start a new list that
4383  we then save in the partition info structure.
4384  */
4385  *work_part_info_used= FALSE;
4386  lex.part_info= new partition_info();/* Indicates MYSQLparse from this place */
4387  if (!lex.part_info)
4388  {
4389  mem_alloc_error(sizeof(partition_info));
4390  goto end;
4391  }
4392  part_info= lex.part_info;
4393  DBUG_PRINT("info", ("Parse: %s", part_buf));
4394 
4395  thd->m_statement_psi= NULL;
4396  if (parse_sql(thd, & parser_state, NULL) ||
4397  part_info->fix_parser_data(thd))
4398  {
4399  thd->free_items();
4400  thd->m_statement_psi= parent_locker;
4401  goto end;
4402  }
4403  thd->m_statement_psi= parent_locker;
4404  /*
4405  The parsed syntax residing in the frm file can still contain defaults.
4406  The reason is that the frm file is sometimes saved outside of this
4407  MySQL Server and used in backup and restore of clusters or partitioned
4408  tables. It is not certain that the restore will restore exactly the
4409  same default partitioning.
4410 
4411  The easiest manner of handling this is to simply continue using the
4412  part_info we already built up during mysql_create_table if we are
4413  in the process of creating a table. If the table already exists we
4414  need to discover the number of partitions for the default parts. Since
4415  the handler object hasn't been created here yet we need to postpone this
4416  to the fix_partition_func method.
4417  */
4418 
4419  DBUG_PRINT("info", ("Successful parse"));
4420  DBUG_PRINT("info", ("default engine = %s, default_db_type = %s",
4421  ha_resolve_storage_engine_name(part_info->default_engine_type),
4422  ha_resolve_storage_engine_name(default_db_type)));
4423  if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE)
4424  {
4425  /*
4426  When we come here we are doing a create table. In this case we
4427  have already done some preparatory work on the old part_info
4428  object. We don't really need this new partition_info object.
4429  Thus we go back to the old partition info object.
4430  We need to free any memory objects allocated on item_free_list
4431  by the parser since we are keeping the old info from the first
4432  parser call in CREATE TABLE.
4433 
4434  This table object can not be used any more. However, since
4435  this is CREATE TABLE, we know that it will be destroyed by the
4436  caller, and rely on that.
4437  */
4438  thd->free_items();
4439  part_info= thd->work_part_info;
4440  *work_part_info_used= true;
4441  }
4442  table->part_info= part_info;
4443  part_info->table= table;
4444  table->file->set_part_info(part_info, TRUE);
4445  if (!part_info->default_engine_type)
4446  part_info->default_engine_type= default_db_type;
4447  DBUG_ASSERT(part_info->default_engine_type == default_db_type);
4448  DBUG_ASSERT(part_info->default_engine_type->db_type != DB_TYPE_UNKNOWN);
4449  DBUG_ASSERT(part_info->default_engine_type != partition_hton);
4450 
4451  {
4452  /*
4453  This code part allocates memory for the serialised item information for
4454  the partition functions. In most cases this is not needed but if the
4455  table is used for SHOW CREATE TABLES or ALTER TABLE that modifies
4456  partition information it is needed and the info is lost if we don't
4457  save it here so unfortunately we have to do it here even if in most
4458  cases it is not needed. This is a consequence of that item trees are
4459  not serialisable.
4460  */
4461  uint part_func_len= part_info->part_func_len;
4462  uint subpart_func_len= part_info->subpart_func_len;
4463  char *part_func_string= NULL;
4464  char *subpart_func_string= NULL;
4465  if ((part_func_len &&
4466  !((part_func_string= (char*) thd->alloc(part_func_len)))) ||
4467  (subpart_func_len &&
4468  !((subpart_func_string= (char*) thd->alloc(subpart_func_len)))))
4469  {
4470  mem_alloc_error(part_func_len);
4471  thd->free_items();
4472  goto end;
4473  }
4474  if (part_func_len)
4475  memcpy(part_func_string, part_info->part_func_string, part_func_len);
4476  if (subpart_func_len)
4477  memcpy(subpart_func_string, part_info->subpart_func_string,
4478  subpart_func_len);
4479  part_info->part_func_string= part_func_string;
4480  part_info->subpart_func_string= subpart_func_string;
4481  }
4482 
4483  result= FALSE;
4484 end:
4485  end_lex_with_single_table(thd, table, old_lex);
4486  thd->variables.character_set_client= old_character_set_client;
4487  DBUG_RETURN(result);
4488 }
4489 
4490 
4491 /*
4492  Set engine type on all partition element objects
4493  SYNOPSIS
4494  set_engine_all_partitions()
4495  part_info Partition info
4496  engine_type Handlerton reference of engine
4497  RETURN VALUES
4498  NONE
4499 */
4500 
4501 static
4502 void
4503 set_engine_all_partitions(partition_info *part_info,
4504  handlerton *engine_type)
4505 {
4506  uint i= 0;
4507  List_iterator<partition_element> part_it(part_info->partitions);
4508  do
4509  {
4510  partition_element *part_elem= part_it++;
4511 
4512  part_elem->engine_type= engine_type;
4513  if (part_info->is_sub_partitioned())
4514  {
4515  List_iterator<partition_element> sub_it(part_elem->subpartitions);
4516  uint j= 0;
4517 
4518  do
4519  {
4520  partition_element *sub_elem= sub_it++;
4521 
4522  sub_elem->engine_type= engine_type;
4523  } while (++j < part_info->num_subparts);
4524  }
4525  } while (++i < part_info->num_parts);
4526 }
4527 
4528 
4542 static int fast_end_partition(THD *thd, ulonglong copied,
4543  ulonglong deleted,
4544  TABLE_LIST *table_list)
4545 {
4546  char tmp_name[80];
4547  DBUG_ENTER("fast_end_partition");
4548 
4549  thd->proc_info="end";
4550 
4551  query_cache_invalidate3(thd, table_list, 0);
4552 
4553  my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
4554  (ulong) (copied + deleted),
4555  (ulong) deleted,
4556  (ulong) 0);
4557  my_ok(thd, (ha_rows) (copied+deleted),0L, tmp_name);
4558  DBUG_RETURN(FALSE);
4559 }
4560 
4561 
4562 /*
4563  We need to check if engine used by all partitions can handle
4564  partitioning natively.
4565 
4566  SYNOPSIS
4567  check_native_partitioned()
4568  create_info Create info in CREATE TABLE
4569  out:ret_val Return value
4570  part_info Partition info
4571  thd Thread object
4572 
4573  RETURN VALUES
4574  Value returned in bool ret_value
4575  TRUE Native partitioning supported by engine
4576  FALSE Need to use partition handler
4577 
4578  Return value from function
4579  TRUE Error
4580  FALSE Success
4581 */
4582 
4583 static bool check_native_partitioned(HA_CREATE_INFO *create_info,bool *ret_val,
4584  partition_info *part_info, THD *thd)
4585 {
4586  bool table_engine_set;
4587  handlerton *engine_type= part_info->default_engine_type;
4588  handlerton *old_engine_type= engine_type;
4589  DBUG_ENTER("check_native_partitioned");
4590 
4591  if (create_info->used_fields & HA_CREATE_USED_ENGINE)
4592  {
4593  table_engine_set= TRUE;
4594  engine_type= create_info->db_type;
4595  }
4596  else
4597  {
4598  table_engine_set= FALSE;
4599  if (thd->lex->sql_command != SQLCOM_CREATE_TABLE)
4600  {
4601  table_engine_set= TRUE;
4602  DBUG_ASSERT(engine_type && engine_type != partition_hton);
4603  }
4604  }
4605  DBUG_PRINT("info", ("engine_type = %s, table_engine_set = %u",
4606  ha_resolve_storage_engine_name(engine_type),
4607  table_engine_set));
4608  if (part_info->check_engine_mix(engine_type, table_engine_set))
4609  goto error;
4610 
4611  /*
4612  All engines are of the same type. Check if this engine supports
4613  native partitioning.
4614  */
4615 
4616  if (!engine_type)
4617  engine_type= old_engine_type;
4618  DBUG_PRINT("info", ("engine_type = %s",
4619  ha_resolve_storage_engine_name(engine_type)));
4620  if (engine_type->partition_flags &&
4621  (engine_type->partition_flags() & HA_CAN_PARTITION))
4622  {
4623  create_info->db_type= engine_type;
4624  DBUG_PRINT("info", ("Changed to native partitioning"));
4625  *ret_val= TRUE;
4626  }
4627  DBUG_RETURN(FALSE);
4628 error:
4629  /*
4630  Mixed engines not yet supported but when supported it will need
4631  the partition handler
4632  */
4633  my_error(ER_MIX_HANDLER_ERROR, MYF(0));
4634  *ret_val= FALSE;
4635  DBUG_RETURN(TRUE);
4636 }
4637 
4638 
4651 bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
4652  enum partition_state part_state)
4653 {
4654  uint part_count= 0;
4655  uint num_parts_found= 0;
4656  List_iterator<partition_element> part_it(tab_part_info->partitions);
4657 
4658  do
4659  {
4660  partition_element *part_elem= part_it++;
4661  if ((alter_info->flags & Alter_info::ALTER_ALL_PARTITION) ||
4662  (is_name_in_list(part_elem->partition_name,
4663  alter_info->partition_names)))
4664  {
4665  /*
4666  Mark the partition.
4667  I.e mark the partition as a partition to be "changed" by
4668  analyzing/optimizing/rebuilding/checking/repairing/...
4669  */
4670  num_parts_found++;
4671  part_elem->part_state= part_state;
4672  DBUG_PRINT("info", ("Setting part_state to %u for partition %s",
4673  part_state, part_elem->partition_name));
4674  }
4675  else
4676  part_elem->part_state= PART_NORMAL;
4677  } while (++part_count < tab_part_info->num_parts);
4678 
4679  if (num_parts_found != alter_info->partition_names.elements &&
4680  !(alter_info->flags & Alter_info::ALTER_ALL_PARTITION))
4681  {
4682  /* Not all given partitions found, revert and return failure */
4683  part_it.rewind();
4684  part_count= 0;
4685  do
4686  {
4687  partition_element *part_elem= part_it++;
4688  part_elem->part_state= PART_NORMAL;
4689  } while (++part_count < tab_part_info->num_parts);
4690  return true;
4691  }
4692  return false;
4693 }
4694 
4695 
4708 bool compare_partition_options(HA_CREATE_INFO *table_create_info,
4709  partition_element *part_elem)
4710 {
4711 #define MAX_COMPARE_PARTITION_OPTION_ERRORS 5
4712  const char *option_diffs[MAX_COMPARE_PARTITION_OPTION_ERRORS + 1];
4713  int i, errors= 0;
4714  DBUG_ENTER("compare_partition_options");
4715  DBUG_ASSERT(!part_elem->tablespace_name &&
4716  !table_create_info->tablespace);
4717 
4718  /*
4719  Note that there are not yet any engine supporting tablespace together
4720  with partitioning. TODO: when there are, add compare.
4721  */
4722  if (part_elem->tablespace_name || table_create_info->tablespace)
4723  option_diffs[errors++]= "TABLESPACE";
4724  if (part_elem->part_max_rows != table_create_info->max_rows)
4725  option_diffs[errors++]= "MAX_ROWS";
4726  if (part_elem->part_min_rows != table_create_info->min_rows)
4727  option_diffs[errors++]= "MIN_ROWS";
4728  if (part_elem->data_file_name || table_create_info->data_file_name)
4729  option_diffs[errors++]= "DATA DIRECTORY";
4730  if (part_elem->index_file_name || table_create_info->index_file_name)
4731  option_diffs[errors++]= "INDEX DIRECTORY";
4732 
4733  for (i= 0; i < errors; i++)
4734  my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0),
4735  option_diffs[i]);
4736  DBUG_RETURN(errors != 0);
4737 }
4738 
4739 
4740 /*
4741  Prepare for ALTER TABLE of partition structure
4742 
4743  @param[in] thd Thread object
4744  @param[in] table Table object
4745  @param[in,out] alter_info Alter information
4746  @param[in,out] create_info Create info for CREATE TABLE
4747  @param[in] alter_ctx ALTER TABLE runtime context
4748  @param[out] partition_changed Boolean indicating whether partition changed
4749  @param[out] fast_alter_table Boolean indicating if fast partition alter is
4750  possible.
4751 
4752  @return Operation status
4753  @retval TRUE Error
4754  @retval FALSE Success
4755 
4756  @note
4757  This method handles all preparations for ALTER TABLE for partitioned
4758  tables.
4759  We need to handle both partition management command such as Add Partition
4760  and others here as well as an ALTER TABLE that completely changes the
4761  partitioning and yet others that don't change anything at all. We start
4762  by checking the partition management variants and then check the general
4763  change patterns.
4764 */
4765 
4766 uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
4767  HA_CREATE_INFO *create_info,
4768  Alter_table_ctx *alter_ctx,
4769  bool *partition_changed,
4770  bool *fast_alter_table)
4771 {
4772  DBUG_ENTER("prep_alter_part_table");
4773 
4774  /* Foreign keys on partitioned tables are not supported, waits for WL#148 */
4775  if (table->part_info && (alter_info->flags & Alter_info::ADD_FOREIGN_KEY ||
4776  alter_info->flags & Alter_info::DROP_FOREIGN_KEY))
4777  {
4778  my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
4779  DBUG_RETURN(TRUE);
4780  }
4781  /* Remove partitioning on a not partitioned table is not possible */
4782  if (!table->part_info && (alter_info->flags &
4783  Alter_info::ALTER_REMOVE_PARTITIONING))
4784  {
4785  my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
4786  DBUG_RETURN(TRUE);
4787  }
4788 
4789  thd->work_part_info= thd->lex->part_info;
4790 
4791  if (thd->work_part_info &&
4792  !(thd->work_part_info= thd->lex->part_info->get_clone()))
4793  DBUG_RETURN(TRUE);
4794 
4795  /* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */
4796  DBUG_ASSERT(!(alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION));
4797 
4798  if (alter_info->flags &
4799  (Alter_info::ALTER_ADD_PARTITION |
4800  Alter_info::ALTER_DROP_PARTITION |
4801  Alter_info::ALTER_COALESCE_PARTITION |
4802  Alter_info::ALTER_REORGANIZE_PARTITION |
4803  Alter_info::ALTER_TABLE_REORG |
4804  Alter_info::ALTER_REBUILD_PARTITION))
4805  {
4806  partition_info *tab_part_info;
4807  partition_info *alt_part_info= thd->work_part_info;
4808  uint flags= 0;
4809  bool is_last_partition_reorged= FALSE;
4810  part_elem_value *tab_max_elem_val= NULL;
4811  part_elem_value *alt_max_elem_val= NULL;
4812  longlong tab_max_range= 0, alt_max_range= 0;
4813 
4814  if (!table->part_info)
4815  {
4816  my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
4817  DBUG_RETURN(TRUE);
4818  }
4819 
4820  /*
4821  Open our intermediate table, we will operate on a temporary instance
4822  of the original table, to be able to skip copying all partitions.
4823  Open it as a copy of the original table, and modify its partition_info
4824  object to allow fast_alter_partition_table to perform the changes.
4825  */
4826  DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
4827  alter_ctx->db,
4828  alter_ctx->table_name,
4829  MDL_INTENTION_EXCLUSIVE));
4830 
4831  tab_part_info= table->part_info;
4832 
4833  if (alter_info->flags & Alter_info::ALTER_TABLE_REORG)
4834  {
4835  uint new_part_no, curr_part_no;
4836  /*
4837  'ALTER TABLE t REORG PARTITION' only allowed with auto partition
4838  if default partitioning is used.
4839  */
4840 
4841  if (tab_part_info->part_type != HASH_PARTITION ||
4842  ((table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) &&
4843  !tab_part_info->use_default_num_partitions) ||
4844  ((!(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)) &&
4845  tab_part_info->use_default_num_partitions))
4846  {
4847  my_error(ER_REORG_NO_PARAM_ERROR, MYF(0));
4848  goto err;
4849  }
4850  new_part_no= table->file->get_default_no_partitions(create_info);
4851  curr_part_no= tab_part_info->num_parts;
4852  if (new_part_no == curr_part_no)
4853  {
4854  /*
4855  No change is needed, we will have the same number of partitions
4856  after the change as before. Thus we can reply ok immediately
4857  without any changes at all.
4858  */
4859  flags= table->file->alter_table_flags(alter_info->flags);
4860  if (flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE))
4861  {
4862  *fast_alter_table= true;
4863  /* Force table re-open for consistency with the main case. */
4864  table->m_needs_reopen= true;
4865  }
4866  else
4867  {
4868  /*
4869  Create copy of partition_info to avoid modifying original
4870  TABLE::part_info, to keep it safe for later use.
4871  */
4872  if (!(tab_part_info= tab_part_info->get_clone()))
4873  DBUG_RETURN(TRUE);
4874  }
4875 
4876  thd->work_part_info= tab_part_info;
4877  DBUG_RETURN(FALSE);
4878  }
4879  else if (new_part_no > curr_part_no)
4880  {
4881  /*
4882  We will add more partitions, we use the ADD PARTITION without
4883  setting the flag for no default number of partitions
4884  */
4885  alter_info->flags|= Alter_info::ALTER_ADD_PARTITION;
4886  thd->work_part_info->num_parts= new_part_no - curr_part_no;
4887  }
4888  else
4889  {
4890  /*
4891  We will remove hash partitions, we use the COALESCE PARTITION
4892  without setting the flag for no default number of partitions
4893  */
4894  alter_info->flags|= Alter_info::ALTER_COALESCE_PARTITION;
4895  alter_info->num_parts= curr_part_no - new_part_no;
4896  }
4897  }
4898  if (!(flags= table->file->alter_table_flags(alter_info->flags)))
4899  {
4900  my_error(ER_PARTITION_FUNCTION_FAILURE, MYF(0));
4901  goto err;
4902  }
4903  if ((flags & (HA_FAST_CHANGE_PARTITION | HA_PARTITION_ONE_PHASE)) != 0)
4904  {
4905  /*
4906  "Fast" change of partitioning is supported in this case.
4907  We will change TABLE::part_info (as this is how we pass
4908  information to storage engine in this case), so the table
4909  must be reopened.
4910  */
4911  *fast_alter_table= true;
4912  table->m_needs_reopen= true;
4913  }
4914  else
4915  {
4916  /*
4917  "Fast" changing of partitioning is not supported. Create
4918  a copy of TABLE::part_info object, so we can modify it safely.
4919  Modifying original TABLE::part_info will cause problems when
4920  we read data from old version of table using this TABLE object
4921  while copying them to new version of table.
4922  */
4923  if (!(tab_part_info= tab_part_info->get_clone()))
4924  DBUG_RETURN(TRUE);
4925  }
4926  DBUG_PRINT("info", ("*fast_alter_table flags: 0x%x", flags));
4927  if ((alter_info->flags & Alter_info::ALTER_ADD_PARTITION) ||
4928  (alter_info->flags & Alter_info::ALTER_REORGANIZE_PARTITION))
4929  {
4930  if (thd->work_part_info->part_type != tab_part_info->part_type)
4931  {
4932  if (thd->work_part_info->part_type == NOT_A_PARTITION)
4933  {
4934  if (tab_part_info->part_type == RANGE_PARTITION)
4935  {
4936  my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), "RANGE");
4937  goto err;
4938  }
4939  else if (tab_part_info->part_type == LIST_PARTITION)
4940  {
4941  my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), "LIST");
4942  goto err;
4943  }
4944  /*
4945  Hash partitions can be altered without parser finds out about
4946  that it is HASH partitioned. So no error here.
4947  */
4948  }
4949  else
4950  {
4951  if (thd->work_part_info->part_type == RANGE_PARTITION)
4952  {
4953  my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
4954  "RANGE", "LESS THAN");
4955  }
4956  else if (thd->work_part_info->part_type == LIST_PARTITION)
4957  {
4958  DBUG_ASSERT(thd->work_part_info->part_type == LIST_PARTITION);
4959  my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
4960  "LIST", "IN");
4961  }
4962  else if (tab_part_info->part_type == RANGE_PARTITION)
4963  {
4964  my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
4965  "RANGE", "LESS THAN");
4966  }
4967  else
4968  {
4969  DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION);
4970  my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
4971  "LIST", "IN");
4972  }
4973  goto err;
4974  }
4975  }
4976  if ((tab_part_info->column_list &&
4977  alt_part_info->num_columns != tab_part_info->num_columns) ||
4978  (!tab_part_info->column_list &&
4979  (tab_part_info->part_type == RANGE_PARTITION ||
4980  tab_part_info->part_type == LIST_PARTITION) &&
4981  alt_part_info->num_columns != 1U) ||
4982  (!tab_part_info->column_list &&
4983  tab_part_info->part_type == HASH_PARTITION &&
4984  alt_part_info->num_columns != 0))
4985  {
4986  my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
4987  goto err;
4988  }
4989  alt_part_info->column_list= tab_part_info->column_list;
4990  if (alt_part_info->fix_parser_data(thd))
4991  {
4992  goto err;
4993  }
4994  }
4995  if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION)
4996  {
4997  /*
4998  We start by moving the new partitions to the list of temporary
4999  partitions. We will then check that the new partitions fit in the
5000  partitioning scheme as currently set-up.
5001  Partitions are always added at the end in ADD PARTITION.
5002  */
5003  uint num_new_partitions= alt_part_info->num_parts;
5004  uint num_orig_partitions= tab_part_info->num_parts;
5005  uint check_total_partitions= num_new_partitions + num_orig_partitions;
5006  uint new_total_partitions= check_total_partitions;
5007  /*
5008  We allow quite a lot of values to be supplied by defaults, however we
5009  must know the number of new partitions in this case.
5010  */
5011  if (thd->lex->no_write_to_binlog &&
5012  tab_part_info->part_type != HASH_PARTITION)
5013  {
5014  my_error(ER_NO_BINLOG_ERROR, MYF(0));
5015  goto err;
5016  }
5017  if (tab_part_info->defined_max_value)
5018  {
5019  my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
5020  goto err;
5021  }
5022  if (num_new_partitions == 0)
5023  {
5024  my_error(ER_ADD_PARTITION_NO_NEW_PARTITION, MYF(0));
5025  goto err;
5026  }
5027  if (tab_part_info->is_sub_partitioned())
5028  {
5029  if (alt_part_info->num_subparts == 0)
5030  alt_part_info->num_subparts= tab_part_info->num_subparts;
5031  else if (alt_part_info->num_subparts != tab_part_info->num_subparts)
5032  {
5033  my_error(ER_ADD_PARTITION_SUBPART_ERROR, MYF(0));
5034  goto err;
5035  }
5036  check_total_partitions= new_total_partitions*
5037  alt_part_info->num_subparts;
5038  }
5039  if (check_total_partitions > MAX_PARTITIONS)
5040  {
5041  my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
5042  goto err;
5043  }
5044  alt_part_info->part_type= tab_part_info->part_type;
5045  alt_part_info->subpart_type= tab_part_info->subpart_type;
5046  if (alt_part_info->set_up_defaults_for_partitioning(table->file,
5047  ULL(0),
5048  tab_part_info->num_parts))
5049  {
5050  goto err;
5051  }
5052 /*
5053 Handling of on-line cases:
5054 
5055 ADD PARTITION for RANGE/LIST PARTITIONING:
5056 ------------------------------------------
5057 For range and list partitions add partition is simply adding a
5058 new empty partition to the table. If the handler support this we
5059 will use the simple method of doing this. The figure below shows
5060 an example of this and the states involved in making this change.
5061 
5062 Existing partitions New added partitions
5063 ------ ------ ------ ------ | ------ ------
5064 | | | | | | | | | | | | |
5065 | p0 | | p1 | | p2 | | p3 | | | p4 | | p5 |
5066 ------ ------ ------ ------ | ------ ------
5067 PART_NORMAL PART_NORMAL PART_NORMAL PART_NORMAL PART_TO_BE_ADDED*2
5068 PART_NORMAL PART_NORMAL PART_NORMAL PART_NORMAL PART_IS_ADDED*2
5069 
5070 The first line is the states before adding the new partitions and the
5071 second line is after the new partitions are added. All the partitions are
5072 in the partitions list, no partitions are placed in the temp_partitions
5073 list.
5074 
5075 ADD PARTITION for HASH PARTITIONING
5076 -----------------------------------
5077 This little figure tries to show the various partitions involved when
5078 adding two new partitions to a linear hash based partitioned table with
5079 four partitions to start with, which lists are used and the states they
5080 pass through. Adding partitions to a normal hash based is similar except
5081 that it is always all the existing partitions that are reorganised not
5082 only a subset of them.
5083 
5084 Existing partitions New added partitions
5085 ------ ------ ------ ------ | ------ ------
5086 | | | | | | | | | | | | |
5087 | p0 | | p1 | | p2 | | p3 | | | p4 | | p5 |
5088 ------ ------ ------ ------ | ------ ------
5089 PART_CHANGED PART_CHANGED PART_NORMAL PART_NORMAL PART_TO_BE_ADDED
5090 PART_IS_CHANGED*2 PART_NORMAL PART_NORMAL PART_IS_ADDED
5091 PART_NORMAL PART_NORMAL PART_NORMAL PART_NORMAL PART_IS_ADDED
5092 
5093 Reorganised existing partitions
5094 ------ ------
5095 | | | |
5096 | p0'| | p1'|
5097 ------ ------
5098 
5099 p0 - p5 will be in the partitions list of partitions.
5100 p0' and p1' will actually not exist as separate objects, there presence can
5101 be deduced from the state of the partition and also the names of those
5102 partitions can be deduced this way.
5103 
5104 After adding the partitions and copying the partition data to p0', p1',
5105 p4 and p5 from p0 and p1 the states change to adapt for the new situation
5106 where p0 and p1 is dropped and replaced by p0' and p1' and the new p4 and
5107 p5 are in the table again.
5108 
5109 The first line above shows the states of the partitions before we start
5110 adding and copying partitions, the second after completing the adding
5111 and copying and finally the third line after also dropping the partitions
5112 that are reorganised.
5113 */
5114  if (*fast_alter_table &&
5115  tab_part_info->part_type == HASH_PARTITION)
5116  {
5117  uint part_no= 0, start_part= 1, start_sec_part= 1;
5118  uint end_part= 0, end_sec_part= 0;
5119  uint upper_2n= tab_part_info->linear_hash_mask + 1;
5120  uint lower_2n= upper_2n >> 1;
5121  bool all_parts= TRUE;
5122  if (tab_part_info->linear_hash_ind &&
5123  num_new_partitions < upper_2n)
5124  {
5125  /*
5126  An analysis of which parts needs reorganisation shows that it is
5127  divided into two intervals. The first interval is those parts
5128  that are reorganised up until upper_2n - 1. From upper_2n and
5129  onwards it starts again from partition 0 and goes on until
5130  it reaches p(upper_2n - 1). If the last new partition reaches
5131  beyond upper_2n - 1 then the first interval will end with
5132  p(lower_2n - 1) and start with p(num_orig_partitions - lower_2n).
5133  If lower_2n partitions are added then p0 to p(lower_2n - 1) will
5134  be reorganised which means that the two interval becomes one
5135  interval at this point. Thus only when adding less than
5136  lower_2n partitions and going beyond a total of upper_2n we
5137  actually get two intervals.
5138 
5139  To exemplify this assume we have 6 partitions to start with and
5140  add 1, 2, 3, 5, 6, 7, 8, 9 partitions.
5141  The first to add after p5 is p6 = 110 in bit numbers. Thus we
5142  can see that 10 = p2 will be partition to reorganise if only one
5143  partition.
5144  If 2 partitions are added we reorganise [p2, p3]. Those two
5145  cases are covered by the second if part below.
5146  If 3 partitions are added we reorganise [p2, p3] U [p0,p0]. This
5147  part is covered by the else part below.
5148  If 5 partitions are added we get [p2,p3] U [p0, p2] = [p0, p3].
5149  This is covered by the first if part where we need the max check
5150  to here use lower_2n - 1.
5151  If 7 partitions are added we get [p2,p3] U [p0, p4] = [p0, p4].
5152  This is covered by the first if part but here we use the first
5153  calculated end_part.
5154  Finally with 9 new partitions we would also reorganise p6 if we
5155  used the method below but we cannot reorganise more partitions
5156  than what we had from the start and thus we simply set all_parts
5157  to TRUE. In this case we don't get into this if-part at all.
5158  */
5159  all_parts= FALSE;
5160  if (num_new_partitions >= lower_2n)
5161  {
5162  /*
5163  In this case there is only one interval since the two intervals
5164  overlap and this starts from zero to last_part_no - upper_2n
5165  */
5166  start_part= 0;
5167  end_part= new_total_partitions - (upper_2n + 1);
5168  end_part= max(lower_2n - 1, end_part);
5169  }
5170  else if (new_total_partitions <= upper_2n)
5171  {
5172  /*
5173  Also in this case there is only one interval since we are not
5174  going over a 2**n boundary
5175  */
5176  start_part= num_orig_partitions - lower_2n;
5177  end_part= start_part + (num_new_partitions - 1);
5178  }
5179  else
5180  {
5181  /* We have two non-overlapping intervals since we are not
5182  passing a 2**n border and we have not at least lower_2n
5183  new parts that would ensure that the intervals become
5184  overlapping.
5185  */
5186  start_part= num_orig_partitions - lower_2n;
5187  end_part= upper_2n - 1;
5188  start_sec_part= 0;
5189  end_sec_part= new_total_partitions - (upper_2n + 1);
5190  }
5191  }
5192  List_iterator<partition_element> tab_it(tab_part_info->partitions);
5193  part_no= 0;
5194  do
5195  {
5196  partition_element *p_elem= tab_it++;
5197  if (all_parts ||
5198  (part_no >= start_part && part_no <= end_part) ||
5199  (part_no >= start_sec_part && part_no <= end_sec_part))
5200  {
5201  p_elem->part_state= PART_CHANGED;
5202  }
5203  } while (++part_no < num_orig_partitions);
5204  }
5205  /*
5206  Need to concatenate the lists here to make it possible to check the
5207  partition info for correctness using check_partition_info.
5208  For on-line add partition we set the state of this partition to
5209  PART_TO_BE_ADDED to ensure that it is known that it is not yet
5210  usable (becomes usable when partition is created and the switch of
5211  partition configuration is made.
5212  */
5213  {
5214  List_iterator<partition_element> alt_it(alt_part_info->partitions);
5215  uint part_count= 0;
5216  do
5217  {
5218  partition_element *part_elem= alt_it++;
5219  if (*fast_alter_table)
5220  part_elem->part_state= PART_TO_BE_ADDED;
5221  if (tab_part_info->partitions.push_back(part_elem))
5222  {
5223  mem_alloc_error(1);
5224  goto err;
5225  }
5226  } while (++part_count < num_new_partitions);
5227  tab_part_info->num_parts+= num_new_partitions;
5228  }
5229  /*
5230  If we specify partitions explicitly we don't use defaults anymore.
5231  Using ADD PARTITION also means that we don't have the default number
5232  of partitions anymore. We use this code also for Table reorganisations
5233  and here we don't set any default flags to FALSE.
5234  */
5235  if (!(alter_info->flags & Alter_info::ALTER_TABLE_REORG))
5236  {
5237  if (!alt_part_info->use_default_partitions)
5238  {
5239  DBUG_PRINT("info", ("part_info: 0x%lx", (long) tab_part_info));
5240  tab_part_info->use_default_partitions= FALSE;
5241  }
5242  tab_part_info->use_default_num_partitions= FALSE;
5243  tab_part_info->is_auto_partitioned= FALSE;
5244  }
5245  }
5246  else if (alter_info->flags & Alter_info::ALTER_DROP_PARTITION)
5247  {
5248  /*
5249  Drop a partition from a range partition and list partitioning is
5250  always safe and can be made more or less immediate. It is necessary
5251  however to ensure that the partition to be removed is safely removed
5252  and that REPAIR TABLE can remove the partition if for some reason the
5253  command to drop the partition failed in the middle.
5254  */
5255  uint part_count= 0;
5256  uint num_parts_dropped= alter_info->partition_names.elements;
5257  uint num_parts_found= 0;
5258  List_iterator<partition_element> part_it(tab_part_info->partitions);
5259 
5260  tab_part_info->is_auto_partitioned= FALSE;
5261  if (!(tab_part_info->part_type == RANGE_PARTITION ||
5262  tab_part_info->part_type == LIST_PARTITION))
5263  {
5264  my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP");
5265  goto err;
5266  }
5267  if (num_parts_dropped >= tab_part_info->num_parts)
5268  {
5269  my_error(ER_DROP_LAST_PARTITION, MYF(0));
5270  goto err;
5271  }
5272  do
5273  {
5274  partition_element *part_elem= part_it++;
5275  if (is_name_in_list(part_elem->partition_name,
5276  alter_info->partition_names))
5277  {
5278  /*
5279  Set state to indicate that the partition is to be dropped.
5280  */
5281  num_parts_found++;
5282  part_elem->part_state= PART_TO_BE_DROPPED;
5283  }
5284  } while (++part_count < tab_part_info->num_parts);
5285  if (num_parts_found != num_parts_dropped)
5286  {
5287  my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "DROP");
5288  goto err;
5289  }
5290  if (table->file->is_fk_defined_on_table_or_index(MAX_KEY))
5291  {
5292  my_error(ER_ROW_IS_REFERENCED, MYF(0));
5293  goto err;
5294  }
5295  tab_part_info->num_parts-= num_parts_dropped;
5296  }
5297  else if (alter_info->flags & Alter_info::ALTER_REBUILD_PARTITION)
5298  {
5299  if (set_part_state(alter_info, tab_part_info, PART_CHANGED))
5300  {
5301  my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REBUILD");
5302  goto err;
5303  }
5304  if (!(*fast_alter_table))
5305  {
5306  table->file->print_error(HA_ERR_WRONG_COMMAND, MYF(0));
5307  goto err;
5308  }
5309  }
5310  else if (alter_info->flags & Alter_info::ALTER_COALESCE_PARTITION)
5311  {
5312  uint num_parts_coalesced= alter_info->num_parts;
5313  uint num_parts_remain= tab_part_info->num_parts - num_parts_coalesced;
5314  List_iterator<partition_element> part_it(tab_part_info->partitions);
5315  if (tab_part_info->part_type != HASH_PARTITION)
5316  {
5317  my_error(ER_COALESCE_ONLY_ON_HASH_PARTITION, MYF(0));
5318  goto err;
5319  }
5320  if (num_parts_coalesced == 0)
5321  {
5322  my_error(ER_COALESCE_PARTITION_NO_PARTITION, MYF(0));
5323  goto err;
5324  }
5325  if (num_parts_coalesced >= tab_part_info->num_parts)
5326  {
5327  my_error(ER_DROP_LAST_PARTITION, MYF(0));
5328  goto err;
5329  }
5330 /*
5331 Online handling:
5332 COALESCE PARTITION:
5333 -------------------
5334 The figure below shows the manner in which partitions are handled when
5335 performing an on-line coalesce partition and which states they go through
5336 at start, after adding and copying partitions and finally after dropping
5337 the partitions to drop. The figure shows an example using four partitions
5338 to start with, using linear hash and coalescing one partition (always the
5339 last partition).
5340 
5341 Using linear hash then all remaining partitions will have a new reorganised
5342 part.
5343 
5344 Existing partitions Coalesced partition
5345 ------ ------ ------ | ------
5346 | | | | | | | | |
5347 | p0 | | p1 | | p2 | | | p3 |
5348 ------ ------ ------ | ------
5349 PART_NORMAL PART_CHANGED PART_NORMAL PART_REORGED_DROPPED
5350 PART_NORMAL PART_IS_CHANGED PART_NORMAL PART_TO_BE_DROPPED
5351 PART_NORMAL PART_NORMAL PART_NORMAL PART_IS_DROPPED
5352 
5353 Reorganised existing partitions
5354  ------
5355  | |
5356  | p1'|
5357  ------
5358 
5359 p0 - p3 is in the partitions list.
5360 The p1' partition will actually not be in any list it is deduced from the
5361 state of p1.
5362 */
5363  {
5364  uint part_count= 0, start_part= 1, start_sec_part= 1;
5365  uint end_part= 0, end_sec_part= 0;
5366  bool all_parts= TRUE;
5367  if (*fast_alter_table &&
5368  tab_part_info->linear_hash_ind)
5369  {
5370  uint upper_2n= tab_part_info->linear_hash_mask + 1;
5371  uint lower_2n= upper_2n >> 1;
5372  all_parts= FALSE;
5373  if (num_parts_coalesced >= lower_2n)
5374  {
5375  all_parts= TRUE;
5376  }
5377  else if (num_parts_remain >= lower_2n)
5378  {
5379  end_part= tab_part_info->num_parts - (lower_2n + 1);
5380  start_part= num_parts_remain - lower_2n;
5381  }
5382  else
5383  {
5384  start_part= 0;
5385  end_part= tab_part_info->num_parts - (lower_2n + 1);
5386  end_sec_part= (lower_2n >> 1) - 1;
5387  start_sec_part= end_sec_part - (lower_2n - (num_parts_remain + 1));
5388  }
5389  }
5390  do
5391  {
5392  partition_element *p_elem= part_it++;
5393  if (*fast_alter_table &&
5394  (all_parts ||
5395  (part_count >= start_part && part_count <= end_part) ||
5396  (part_count >= start_sec_part && part_count <= end_sec_part)))
5397  p_elem->part_state= PART_CHANGED;
5398  if (++part_count > num_parts_remain)
5399  {
5400  if (*fast_alter_table)
5401  p_elem->part_state= PART_REORGED_DROPPED;
5402  else
5403  part_it.remove();
5404  }
5405  } while (part_count < tab_part_info->num_parts);
5406  tab_part_info->num_parts= num_parts_remain;
5407  }
5408  if (!(alter_info->flags & Alter_info::ALTER_TABLE_REORG))
5409  {
5410  tab_part_info->use_default_num_partitions= FALSE;
5411  tab_part_info->is_auto_partitioned= FALSE;
5412  }
5413  }
5414  else if (alter_info->flags & Alter_info::ALTER_REORGANIZE_PARTITION)
5415  {
5416  /*
5417  Reorganise partitions takes a number of partitions that are next
5418  to each other (at least for RANGE PARTITIONS) and then uses those
5419  to create a set of new partitions. So data is copied from those
5420  partitions into the new set of partitions. Those new partitions
5421  can have more values in the LIST value specifications or less both
5422  are allowed. The ranges can be different but since they are
5423  changing a set of consecutive partitions they must cover the same
5424  range as those changed from.
5425  This command can be used on RANGE and LIST partitions.
5426  */
5427  uint num_parts_reorged= alter_info->partition_names.elements;
5428  uint num_parts_new= thd->work_part_info->partitions.elements;
5429  uint check_total_partitions;
5430 
5431  tab_part_info->is_auto_partitioned= FALSE;
5432  if (num_parts_reorged > tab_part_info->num_parts)
5433  {
5434  my_error(ER_REORG_PARTITION_NOT_EXIST, MYF(0));
5435  goto err;
5436  }
5437  if (!(tab_part_info->part_type == RANGE_PARTITION ||
5438  tab_part_info->part_type == LIST_PARTITION) &&
5439  (num_parts_new != num_parts_reorged))
5440  {
5441  my_error(ER_REORG_HASH_ONLY_ON_SAME_NO, MYF(0));
5442  goto err;
5443  }
5444  if (tab_part_info->is_sub_partitioned() &&
5445  alt_part_info->num_subparts &&
5446  alt_part_info->num_subparts != tab_part_info->num_subparts)
5447  {
5448  my_error(ER_PARTITION_WRONG_NO_SUBPART_ERROR, MYF(0));
5449  goto err;
5450  }
5451  check_total_partitions= tab_part_info->num_parts + num_parts_new;
5452  check_total_partitions-= num_parts_reorged;
5453  if (check_total_partitions > MAX_PARTITIONS)
5454  {
5455  my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
5456  goto err;
5457  }
5458  alt_part_info->part_type= tab_part_info->part_type;
5459  alt_part_info->subpart_type= tab_part_info->subpart_type;
5460  alt_part_info->num_subparts= tab_part_info->num_subparts;
5461  DBUG_ASSERT(!alt_part_info->use_default_partitions);
5462  /* We specified partitions explicitly so don't use defaults anymore. */
5463  tab_part_info->use_default_partitions= FALSE;
5464  if (alt_part_info->set_up_defaults_for_partitioning(table->file,
5465  ULL(0),
5466  0))
5467  {
5468  goto err;
5469  }
5470 /*
5471 Online handling:
5472 REORGANIZE PARTITION:
5473 ---------------------
5474 The figure exemplifies the handling of partitions, their state changes and
5475 how they are organised. It exemplifies four partitions where two of the
5476 partitions are reorganised (p1 and p2) into two new partitions (p4 and p5).
5477 The reason of this change could be to change range limits, change list
5478 values or for hash partitions simply reorganise the partition which could
5479 also involve moving them to new disks or new node groups (MySQL Cluster).
5480 
5481 Existing partitions
5482 ------ ------ ------ ------
5483 | | | | | | | |
5484 | p0 | | p1 | | p2 | | p3 |
5485 ------ ------ ------ ------
5486 PART_NORMAL PART_TO_BE_REORGED PART_NORMAL
5487 PART_NORMAL PART_TO_BE_DROPPED PART_NORMAL
5488 PART_NORMAL PART_IS_DROPPED PART_NORMAL
5489 
5490 Reorganised new partitions (replacing p1 and p2)
5491 ------ ------
5492 | | | |
5493 | p4 | | p5 |
5494 ------ ------
5495 PART_TO_BE_ADDED
5496 PART_IS_ADDED
5497 PART_IS_ADDED
5498 
5499 All unchanged partitions and the new partitions are in the partitions list
5500 in the order they will have when the change is completed. The reorganised
5501 partitions are placed in the temp_partitions list. PART_IS_ADDED is only a
5502 temporary state not written in the frm file. It is used to ensure we write
5503 the generated partition syntax in a correct manner.
5504 */
5505  {
5506  List_iterator<partition_element> tab_it(tab_part_info->partitions);
5507  uint part_count= 0;
5508  bool found_first= FALSE;
5509  bool found_last= FALSE;
5510  uint drop_count= 0;
5511  do
5512  {
5513  partition_element *part_elem= tab_it++;
5514  is_last_partition_reorged= FALSE;
5515  if (is_name_in_list(part_elem->partition_name,
5516  alter_info->partition_names))
5517  {
5518  is_last_partition_reorged= TRUE;
5519  drop_count++;
5520  if (tab_part_info->column_list)
5521  {
5522  List_iterator<part_elem_value> p(part_elem->list_val_list);
5523  tab_max_elem_val= p++;
5524  }
5525  else
5526  tab_max_range= part_elem->range_value;
5527  if (*fast_alter_table &&
5528  tab_part_info->temp_partitions.push_back(part_elem))
5529  {
5530  mem_alloc_error(1);
5531  goto err;
5532  }
5533  if (*fast_alter_table)
5534  part_elem->part_state= PART_TO_BE_REORGED;
5535  if (!found_first)
5536  {
5537  uint alt_part_count= 0;
5538  partition_element *alt_part_elem;
5540  alt_it(alt_part_info->partitions);
5541  found_first= TRUE;
5542  do
5543  {
5544  alt_part_elem= alt_it++;
5545  if (tab_part_info->column_list)
5546  {
5547  List_iterator<part_elem_value> p(alt_part_elem->list_val_list);
5548  alt_max_elem_val= p++;
5549  }
5550  else
5551  alt_max_range= alt_part_elem->range_value;
5552 
5553  if (*fast_alter_table)
5554  alt_part_elem->part_state= PART_TO_BE_ADDED;
5555  if (alt_part_count == 0)
5556  tab_it.replace(alt_part_elem);
5557  else
5558  tab_it.after(alt_part_elem);
5559  } while (++alt_part_count < num_parts_new);
5560  }
5561  else if (found_last)
5562  {
5563  my_error(ER_CONSECUTIVE_REORG_PARTITIONS, MYF(0));
5564  goto err;
5565  }
5566  else
5567  tab_it.remove();
5568  }
5569  else
5570  {
5571  if (found_first)
5572  found_last= TRUE;
5573  }
5574  } while (++part_count < tab_part_info->num_parts);
5575  if (drop_count != num_parts_reorged)
5576  {
5577  my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REORGANIZE");
5578  goto err;
5579  }
5580  tab_part_info->num_parts= check_total_partitions;
5581  }
5582  }
5583  else
5584  {
5585  DBUG_ASSERT(FALSE);
5586  }
5587  *partition_changed= TRUE;
5588  thd->work_part_info= tab_part_info;
5589  if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION ||
5590  alter_info->flags & Alter_info::ALTER_REORGANIZE_PARTITION)
5591  {
5592  if (tab_part_info->use_default_subpartitions &&
5593  !alt_part_info->use_default_subpartitions)
5594  {
5595  tab_part_info->use_default_subpartitions= FALSE;
5596  tab_part_info->use_default_num_subpartitions= FALSE;
5597  }
5598  if (tab_part_info->check_partition_info(thd, (handlerton**)NULL,
5599  table->file, ULL(0), TRUE))
5600  {
5601  goto err;
5602  }
5603  /*
5604  The check below needs to be performed after check_partition_info
5605  since this function "fixes" the item trees of the new partitions
5606  to reorganize into
5607  */
5608  if (alter_info->flags == Alter_info::ALTER_REORGANIZE_PARTITION &&
5609  tab_part_info->part_type == RANGE_PARTITION &&
5610  ((is_last_partition_reorged &&
5611  (tab_part_info->column_list ?
5612  (tab_part_info->compare_column_values(
5613  alt_max_elem_val->col_val_array,
5614  tab_max_elem_val->col_val_array) < 0) :
5615  alt_max_range < tab_max_range)) ||
5616  (!is_last_partition_reorged &&
5617  (tab_part_info->column_list ?
5618  (tab_part_info->compare_column_values(
5619  alt_max_elem_val->col_val_array,
5620  tab_max_elem_val->col_val_array) != 0) :
5621  alt_max_range != tab_max_range))))
5622  {
5623  /*
5624  For range partitioning the total resulting range before and
5625  after the change must be the same except in one case. This is
5626  when the last partition is reorganised, in this case it is
5627  acceptable to increase the total range.
5628  The reason is that it is not allowed to have "holes" in the
5629  middle of the ranges and thus we should not allow to reorganise
5630  to create "holes".
5631  */
5632  my_error(ER_REORG_OUTSIDE_RANGE, MYF(0));
5633  goto err;
5634  }
5635  }
5636  }
5637  else
5638  {
5639  /*
5640  When thd->lex->part_info has a reference to a partition_info the
5641  ALTER TABLE contained a definition of a partitioning.
5642 
5643  Case I:
5644  If there was a partition before and there is a new one defined.
5645  We use the new partitioning. The new partitioning is already
5646  defined in the correct variable so no work is needed to
5647  accomplish this.
5648  We do however need to update partition_changed to ensure that not
5649  only the frm file is changed in the ALTER TABLE command.
5650 
5651  Case IIa:
5652  There was a partitioning before and there is no new one defined.
5653  Also the user has not specified to remove partitioning explicitly.
5654 
5655  We use the old partitioning also for the new table. We do this
5656  by assigning the partition_info from the table loaded in
5657  open_table to the partition_info struct used by mysql_create_table
5658  later in this method.
5659 
5660  Case IIb:
5661  There was a partitioning before and there is no new one defined.
5662  The user has specified explicitly to remove partitioning
5663 
5664  Since the user has specified explicitly to remove partitioning
5665  we override the old partitioning info and create a new table using
5666  the specified engine.
5667  In this case the partition also is changed.
5668 
5669  Case III:
5670  There was no partitioning before altering the table, there is
5671  partitioning defined in the altered table. Use the new partitioning.
5672  No work needed since the partitioning info is already in the
5673  correct variable.
5674 
5675  In this case we discover one case where the new partitioning is using
5676  the same partition function as the default (PARTITION BY KEY or
5677  PARTITION BY LINEAR KEY with the list of fields equal to the primary
5678  key fields OR PARTITION BY [LINEAR] KEY() for tables without primary
5679  key)
5680  Also here partition has changed and thus a new table must be
5681  created.
5682 
5683  Case IV:
5684  There was no partitioning before and no partitioning defined.
5685  Obviously no work needed.
5686  */
5687  partition_info *tab_part_info= table->part_info;
5688 
5689  if (tab_part_info)
5690  {
5691  if (alter_info->flags & Alter_info::ALTER_REMOVE_PARTITIONING)
5692  {
5693  DBUG_PRINT("info", ("Remove partitioning"));
5694  if (!(create_info->used_fields & HA_CREATE_USED_ENGINE))
5695  {
5696  DBUG_PRINT("info", ("No explicit engine used"));
5697  create_info->db_type= tab_part_info->default_engine_type;
5698  }
5699  DBUG_PRINT("info", ("New engine type: %s",
5700  ha_resolve_storage_engine_name(create_info->db_type)));
5701  thd->work_part_info= NULL;
5702  *partition_changed= TRUE;
5703  }
5704  else if (!thd->work_part_info)
5705  {
5706  /*
5707  Retain partitioning but possibly with a new storage engine
5708  beneath.
5709 
5710  Create a copy of TABLE::part_info to be able to modify it freely.
5711  */
5712  if (!(tab_part_info= tab_part_info->get_clone()))
5713  DBUG_RETURN(TRUE);
5714  thd->work_part_info= tab_part_info;
5715  if (create_info->used_fields & HA_CREATE_USED_ENGINE &&
5716  create_info->db_type != tab_part_info->default_engine_type)
5717  {
5718  /*
5719  Make sure change of engine happens to all partitions.
5720  */
5721  DBUG_PRINT("info", ("partition changed"));
5722  if (tab_part_info->is_auto_partitioned)
5723  {
5724  /*
5725  If the user originally didn't specify partitioning to be
5726  used we can remove it now.
5727  */
5728  thd->work_part_info= NULL;
5729  }
5730  else
5731  {
5732  /*
5733  Ensure that all partitions have the proper engine set-up
5734  */
5735  set_engine_all_partitions(thd->work_part_info,
5736  create_info->db_type);
5737  }
5738  *partition_changed= TRUE;
5739  }
5740  }
5741  }
5742  if (thd->work_part_info)
5743  {
5744  partition_info *part_info= thd->work_part_info;
5745  bool is_native_partitioned= FALSE;
5746  /*
5747  Need to cater for engine types that can handle partition without
5748  using the partition handler.
5749  */
5750  if (part_info != tab_part_info)
5751  {
5752  if (part_info->fix_parser_data(thd))
5753  {
5754  goto err;
5755  }
5756  /*
5757  Compare the old and new part_info. If only key_algorithm
5758  change is done, don't consider it as changed partitioning (to avoid
5759  rebuild). This is to handle KEY (numeric_cols) partitioned tables
5760  created in 5.1. For more info, see bug#14521864.
5761  */
5762  if (alter_info->flags != Alter_info::ALTER_PARTITION ||
5763  !table->part_info ||
5764  alter_info->requested_algorithm !=
5765  Alter_info::ALTER_TABLE_ALGORITHM_INPLACE ||
5766  !table->part_info->has_same_partitioning(part_info))
5767  {
5768  DBUG_PRINT("info", ("partition changed"));
5769  *partition_changed= true;
5770  }
5771  }
5772  /*
5773  Set up partition default_engine_type either from the create_info
5774  or from the previus table
5775  */
5776  if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5777  part_info->default_engine_type= create_info->db_type;
5778  else
5779  {
5780  if (tab_part_info)
5781  part_info->default_engine_type= tab_part_info->default_engine_type;
5782  else
5783  part_info->default_engine_type= create_info->db_type;
5784  }
5785  DBUG_ASSERT(part_info->default_engine_type &&
5786  part_info->default_engine_type != partition_hton);
5787  if (check_native_partitioned(create_info, &is_native_partitioned,
5788  part_info, thd))
5789  {
5790  goto err;
5791  }
5792  if (!is_native_partitioned)
5793  {
5794  DBUG_ASSERT(create_info->db_type);
5795  create_info->db_type= partition_hton;
5796  }
5797  }
5798  }
5799  DBUG_RETURN(FALSE);
5800 err:
5801  *fast_alter_table= false;
5802  DBUG_RETURN(TRUE);
5803 }
5804 
5805 
5806 /*
5807  Change partitions, used to implement ALTER TABLE ADD/REORGANIZE/COALESCE
5808  partitions. This method is used to implement both single-phase and multi-
5809  phase implementations of ADD/REORGANIZE/COALESCE partitions.
5810 
5811  SYNOPSIS
5812  mysql_change_partitions()
5813  lpt Struct containing parameters
5814 
5815  RETURN VALUES
5816  TRUE Failure
5817  FALSE Success
5818 
5819  DESCRIPTION
5820  Request handler to add partitions as set in states of the partition
5821 
5822  Elements of the lpt parameters used:
5823  create_info Create information used to create partitions
5824  db Database name
5825  table_name Table name
5826  copied Output parameter where number of copied
5827  records are added
5828  deleted Output parameter where number of deleted
5829  records are added
5830 */
5831 
5832 static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
5833 {
5834  char path[FN_REFLEN+1];
5835  int error;
5836  handler *file= lpt->table->file;
5837  THD *thd= lpt->thd;
5838  DBUG_ENTER("mysql_change_partitions");
5839 
5840  build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
5841 
5842  if(mysql_trans_prepare_alter_copy_data(thd))
5843  DBUG_RETURN(TRUE);
5844 
5845  /* TODO: test if bulk_insert would increase the performance */
5846 
5847  if ((error= file->ha_change_partitions(lpt->create_info, path, &lpt->copied,
5848  &lpt->deleted, lpt->pack_frm_data,
5849  lpt->pack_frm_len)))
5850  {
5851  file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
5852  }
5853 
5854  if (mysql_trans_commit_alter_copy_data(thd))
5855  error= 1; /* The error has been reported */
5856 
5857  DBUG_RETURN(test(error));
5858 }
5859 
5860 
5861 /*
5862  Rename partitions in an ALTER TABLE of partitions
5863 
5864  SYNOPSIS
5865  mysql_rename_partitions()
5866  lpt Struct containing parameters
5867 
5868  RETURN VALUES
5869  TRUE Failure
5870  FALSE Success
5871 
5872  DESCRIPTION
5873  Request handler to rename partitions as set in states of the partition
5874 
5875  Parameters used:
5876  db Database name
5877  table_name Table name
5878 */
5879 
5880 static bool mysql_rename_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
5881 {
5882  char path[FN_REFLEN+1];
5883  int error;
5884  DBUG_ENTER("mysql_rename_partitions");
5885 
5886  build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
5887  if ((error= lpt->table->file->ha_rename_partitions(path)))
5888  {
5889  if (error != 1)
5890  lpt->table->file->print_error(error, MYF(0));
5891  DBUG_RETURN(TRUE);
5892  }
5893  DBUG_RETURN(FALSE);
5894 }
5895 
5896 
5897 /*
5898  Drop partitions in an ALTER TABLE of partitions
5899 
5900  SYNOPSIS
5901  mysql_drop_partitions()
5902  lpt Struct containing parameters
5903 
5904  RETURN VALUES
5905  TRUE Failure
5906  FALSE Success
5907  DESCRIPTION
5908  Drop the partitions marked with PART_TO_BE_DROPPED state and remove
5909  those partitions from the list.
5910 
5911  Parameters used:
5912  table Table object
5913  db Database name
5914  table_name Table name
5915 */
5916 
5917 static bool mysql_drop_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
5918 {
5919  char path[FN_REFLEN+1];
5920  partition_info *part_info= lpt->table->part_info;
5921  List_iterator<partition_element> part_it(part_info->partitions);
5922  uint i= 0;
5923  uint remove_count= 0;
5924  int error;
5925  DBUG_ENTER("mysql_drop_partitions");
5926 
5927  DBUG_ASSERT(lpt->thd->mdl_context.is_lock_owner(MDL_key::TABLE,
5928  lpt->table->s->db.str,
5929  lpt->table->s->table_name.str,
5930  MDL_EXCLUSIVE));
5931 
5932  build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0);
5933  if ((error= lpt->table->file->ha_drop_partitions(path)))
5934  {
5935  lpt->table->file->print_error(error, MYF(0));
5936  DBUG_RETURN(TRUE);
5937  }
5938  do
5939  {
5940  partition_element *part_elem= part_it++;
5941  if (part_elem->part_state == PART_IS_DROPPED)
5942  {
5943  part_it.remove();
5944  remove_count++;
5945  }
5946  } while (++i < part_info->num_parts);
5947  part_info->num_parts-= remove_count;
5948  DBUG_RETURN(FALSE);
5949 }
5950 
5951 
5952 /*
5953  Insert log entry into list
5954  SYNOPSIS
5955  insert_part_info_log_entry_list()
5956  log_entry
5957  RETURN VALUES
5958  NONE
5959 */
5960 
5961 static void insert_part_info_log_entry_list(partition_info *part_info,
5962  DDL_LOG_MEMORY_ENTRY *log_entry)
5963 {
5964  log_entry->next_active_log_entry= part_info->first_log_entry;
5965  part_info->first_log_entry= log_entry;
5966 }
5967 
5968 
5969 /*
5970  Release all log entries for this partition info struct
5971  SYNOPSIS
5972  release_part_info_log_entries()
5973  first_log_entry First log entry in list to release
5974  RETURN VALUES
5975  NONE
5976 */
5977 
5978 static void release_part_info_log_entries(DDL_LOG_MEMORY_ENTRY *log_entry)
5979 {
5980  DBUG_ENTER("release_part_info_log_entries");
5981 
5982  while (log_entry)
5983  {
5984  release_ddl_log_memory_entry(log_entry);
5985  log_entry= log_entry->next_active_log_entry;
5986  }
5987  DBUG_VOID_RETURN;
5988 }
5989 
5990 
5991 /*
5992  Log an delete/rename frm file
5993  SYNOPSIS
5994  write_log_replace_delete_frm()
5995  lpt Struct for parameters
5996  next_entry Next reference to use in log record
5997  from_path Name to rename from
5998  to_path Name to rename to
5999  replace_flag TRUE if replace, else delete
6000  RETURN VALUES
6001  TRUE Error
6002  FALSE Success
6003  DESCRIPTION
6004  Support routine that writes a replace or delete of an frm file into the
6005  ddl log. It also inserts an entry that keeps track of used space into
6006  the partition info object
6007 */
6008 
6009 static bool write_log_replace_delete_frm(ALTER_PARTITION_PARAM_TYPE *lpt,
6010  uint next_entry,
6011  const char *from_path,
6012  const char *to_path,
6013  bool replace_flag)
6014 {
6015  DDL_LOG_ENTRY ddl_log_entry;
6016  DDL_LOG_MEMORY_ENTRY *log_entry;
6017  DBUG_ENTER("write_log_replace_delete_frm");
6018 
6019  if (replace_flag)
6020  ddl_log_entry.action_type= DDL_LOG_REPLACE_ACTION;
6021  else
6022  ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
6023  ddl_log_entry.next_entry= next_entry;
6024  ddl_log_entry.handler_name= reg_ext;
6025  ddl_log_entry.name= to_path;
6026  if (replace_flag)
6027  ddl_log_entry.from_name= from_path;
6028  if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
6029  {
6030  DBUG_RETURN(TRUE);
6031  }
6032  insert_part_info_log_entry_list(lpt->part_info, log_entry);
6033  DBUG_RETURN(FALSE);
6034 }
6035 
6036 
6037 /*
6038  Log final partition changes in change partition
6039  SYNOPSIS
6040  write_log_changed_partitions()
6041  lpt Struct containing parameters
6042  RETURN VALUES
6043  TRUE Error
6044  FALSE Success
6045  DESCRIPTION
6046  This code is used to perform safe ADD PARTITION for HASH partitions
6047  and COALESCE for HASH partitions and REORGANIZE for any type of
6048  partitions.
6049  We prepare entries for all partitions except the reorganised partitions
6050  in REORGANIZE partition, those are handled by
6051  write_log_dropped_partitions. For those partitions that are replaced
6052  special care is needed to ensure that this is performed correctly and
6053  this requires a two-phased approach with this log as a helper for this.
6054 
6055  This code is closely intertwined with the code in rename_partitions in
6056  the partition handler.
6057 */
6058 
6059 static bool write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
6060  uint *next_entry, const char *path)
6061 {
6062  DDL_LOG_ENTRY ddl_log_entry;
6063  partition_info *part_info= lpt->part_info;
6064  DDL_LOG_MEMORY_ENTRY *log_entry;
6065  char tmp_path[FN_REFLEN];
6066  char normal_path[FN_REFLEN];
6067  List_iterator<partition_element> part_it(part_info->partitions);
6068  uint temp_partitions= part_info->temp_partitions.elements;
6069  uint num_elements= part_info->partitions.elements;
6070  uint i= 0;
6071  DBUG_ENTER("write_log_changed_partitions");
6072 
6073  do
6074  {
6075  partition_element *part_elem= part_it++;
6076  if (part_elem->part_state == PART_IS_CHANGED ||
6077  (part_elem->part_state == PART_IS_ADDED && temp_partitions))
6078  {
6079  if (part_info->is_sub_partitioned())
6080  {
6081  List_iterator<partition_element> sub_it(part_elem->subpartitions);
6082  uint num_subparts= part_info->num_subparts;
6083  uint j= 0;
6084  do
6085  {
6086  partition_element *sub_elem= sub_it++;
6087  ddl_log_entry.next_entry= *next_entry;
6088  ddl_log_entry.handler_name=
6089  ha_resolve_storage_engine_name(sub_elem->engine_type);
6090  create_subpartition_name(tmp_path, path,
6091  part_elem->partition_name,
6092  sub_elem->partition_name,
6093  TEMP_PART_NAME);
6094  create_subpartition_name(normal_path, path,
6095  part_elem->partition_name,
6096  sub_elem->partition_name,
6097  NORMAL_PART_NAME);
6098  ddl_log_entry.name= normal_path;
6099  ddl_log_entry.from_name= tmp_path;
6100  if (part_elem->part_state == PART_IS_CHANGED)
6101  ddl_log_entry.action_type= DDL_LOG_REPLACE_ACTION;
6102  else
6103  ddl_log_entry.action_type= DDL_LOG_RENAME_ACTION;
6104  if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
6105  {
6106  DBUG_RETURN(TRUE);
6107  }
6108  *next_entry= log_entry->entry_pos;
6109  sub_elem->log_entry= log_entry;
6110  insert_part_info_log_entry_list(part_info, log_entry);
6111  } while (++j < num_subparts);
6112  }
6113  else
6114  {
6115  ddl_log_entry.next_entry= *next_entry;
6116  ddl_log_entry.handler_name=
6117  ha_resolve_storage_engine_name(part_elem->engine_type);
6118  create_partition_name(tmp_path, path,
6119  part_elem->partition_name,
6120  TEMP_PART_NAME, TRUE);
6121  create_partition_name(normal_path, path,
6122  part_elem->partition_name,
6123  NORMAL_PART_NAME, TRUE);
6124  ddl_log_entry.name= normal_path;
6125  ddl_log_entry.from_name= tmp_path;
6126  if (part_elem->part_state == PART_IS_CHANGED)
6127  ddl_log_entry.action_type= DDL_LOG_REPLACE_ACTION;
6128  else
6129  ddl_log_entry.action_type= DDL_LOG_RENAME_ACTION;
6130  if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
6131  {
6132  DBUG_RETURN(TRUE);
6133  }
6134  *next_entry= log_entry->entry_pos;
6135  part_elem->log_entry= log_entry;
6136  insert_part_info_log_entry_list(part_info, log_entry);
6137  }
6138  }
6139  } while (++i < num_elements);
6140  DBUG_RETURN(FALSE);
6141 }
6142 
6143 
6144 /*
6145  Log dropped partitions
6146  SYNOPSIS
6147  write_log_dropped_partitions()
6148  lpt Struct containing parameters
6149  RETURN VALUES
6150  TRUE Error
6151  FALSE Success
6152 */
6153 
6154 static bool write_log_dropped_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
6155  uint *next_entry,
6156  const char *path,
6157  bool temp_list)
6158 {
6159  DDL_LOG_ENTRY ddl_log_entry;
6160  partition_info *part_info= lpt->part_info;
6161  DDL_LOG_MEMORY_ENTRY *log_entry;
6162  char tmp_path[FN_LEN];
6163  List_iterator<partition_element> part_it(part_info->partitions);
6164  List_iterator<partition_element> temp_it(part_info->temp_partitions);
6165  uint num_temp_partitions= part_info->temp_partitions.elements;
6166  uint num_elements= part_info->partitions.elements;
6167  DBUG_ENTER("write_log_dropped_partitions");
6168 
6169  ddl_log_entry.action_type= DDL_LOG_DELETE_ACTION;
6170  if (temp_list)
6171  num_elements= num_temp_partitions;
6172  while (num_elements--)
6173  {
6174  partition_element *part_elem;
6175  if (temp_list)
6176  part_elem= temp_it++;
6177  else
6178  part_elem= part_it++;
6179  if (part_elem->part_state == PART_TO_BE_DROPPED ||
6180  part_elem->part_state == PART_TO_BE_ADDED ||
6181  part_elem->part_state == PART_CHANGED)
6182  {
6183  uint name_variant;
6184  if (part_elem->part_state == PART_CHANGED ||
6185  (part_elem->part_state == PART_TO_BE_ADDED &&
6186  num_temp_partitions))
6187  name_variant= TEMP_PART_NAME;
6188  else
6189  name_variant= NORMAL_PART_NAME;
6190  if (part_info->is_sub_partitioned())
6191  {
6192  List_iterator<partition_element> sub_it(part_elem->subpartitions);
6193  uint num_subparts= part_info->num_subparts;
6194  uint j= 0;
6195  do
6196  {
6197  partition_element *sub_elem= sub_it++;
6198  ddl_log_entry.next_entry= *next_entry;
6199  ddl_log_entry.handler_name=
6200  ha_resolve_storage_engine_name(sub_elem->engine_type);
6201  create_subpartition_name(tmp_path, path,
6202  part_elem->partition_name,
6203  sub_elem->partition_name,
6204  name_variant);
6205  ddl_log_entry.name= tmp_path;
6206  if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
6207  {
6208  DBUG_RETURN(TRUE);
6209  }
6210  *next_entry= log_entry->entry_pos;
6211  sub_elem->log_entry= log_entry;
6212  insert_part_info_log_entry_list(part_info, log_entry);
6213  } while (++j < num_subparts);
6214  }
6215  else
6216  {
6217  ddl_log_entry.next_entry= *next_entry;
6218  ddl_log_entry.handler_name=
6219  ha_resolve_storage_engine_name(part_elem->engine_type);
6220  create_partition_name(tmp_path, path,
6221  part_elem->partition_name,
6222  name_variant, TRUE);
6223  ddl_log_entry.name= tmp_path;
6224  if (write_ddl_log_entry(&ddl_log_entry, &log_entry))
6225  {
6226  DBUG_RETURN(TRUE);
6227  }
6228  *next_entry= log_entry->entry_pos;
6229  part_elem->log_entry= log_entry;
6230  insert_part_info_log_entry_list(part_info, log_entry);
6231  }
6232  }
6233  }
6234  DBUG_RETURN(FALSE);
6235 }
6236 
6237 
6238 /*
6239  Set execute log entry in ddl log for this partitioned table
6240  SYNOPSIS
6241  set_part_info_exec_log_entry()
6242  part_info Partition info object
6243  exec_log_entry Log entry
6244  RETURN VALUES
6245  NONE
6246 */
6247 
6248 static void set_part_info_exec_log_entry(partition_info *part_info,
6249  DDL_LOG_MEMORY_ENTRY *exec_log_entry)
6250 {
6251  part_info->exec_log_entry= exec_log_entry;
6252  exec_log_entry->next_active_log_entry= NULL;
6253 }
6254 
6255 
6256 /*
6257  Write the log entry to ensure that the shadow frm file is removed at
6258  crash.
6259  SYNOPSIS
6260  write_log_drop_shadow_frm()
6261  lpt Struct containing parameters
6262  install_frm Should we log action to install shadow frm or should
6263  the action be to remove the shadow frm file.
6264  RETURN VALUES
6265  TRUE Error
6266  FALSE Success
6267  DESCRIPTION
6268  Prepare an entry to the ddl log indicating a drop/install of the shadow frm
6269  file and its corresponding handler file.
6270 */
6271 
6272 static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
6273 {
6274  partition_info *part_info= lpt->part_info;
6275  DDL_LOG_MEMORY_ENTRY *log_entry;
6276  DDL_LOG_MEMORY_ENTRY *exec_log_entry= NULL;
6277  char shadow_path[FN_REFLEN + 1];
6278  DBUG_ENTER("write_log_drop_shadow_frm");
6279 
6280  build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
6281  mysql_mutex_lock(&LOCK_gdl);
6282  if (write_log_replace_delete_frm(lpt, 0UL, NULL,
6283  (const char*)shadow_path, FALSE))
6284  goto error;
6285  log_entry= part_info->first_log_entry;
6286  if (write_execute_ddl_log_entry(log_entry->entry_pos,
6287  FALSE, &exec_log_entry))
6288  goto error;
6289  mysql_mutex_unlock(&LOCK_gdl);
6290  set_part_info_exec_log_entry(part_info, exec_log_entry);
6291  DBUG_RETURN(FALSE);
6292 
6293 error:
6294  release_part_info_log_entries(part_info->first_log_entry);
6295  mysql_mutex_unlock(&LOCK_gdl);
6296  part_info->first_log_entry= NULL;
6297  my_error(ER_DDL_LOG_ERROR, MYF(0));
6298  DBUG_RETURN(TRUE);
6299 }
6300 
6301 
6302 /*
6303  Log renaming of shadow frm to real frm name and dropping of old frm
6304  SYNOPSIS
6305  write_log_rename_frm()
6306  lpt Struct containing parameters
6307  RETURN VALUES
6308  TRUE Error
6309  FALSE Success
6310  DESCRIPTION
6311  Prepare an entry to ensure that we complete the renaming of the frm
6312  file if failure occurs in the middle of the rename process.
6313 */
6314 
6315 static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt)
6316 {
6317  partition_info *part_info= lpt->part_info;
6318  DDL_LOG_MEMORY_ENTRY *log_entry;
6319  DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
6320  char path[FN_REFLEN + 1];
6321  char shadow_path[FN_REFLEN + 1];
6322  DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
6323  DBUG_ENTER("write_log_rename_frm");
6324 
6325  part_info->first_log_entry= NULL;
6326  build_table_filename(path, sizeof(path) - 1, lpt->db,
6327  lpt->table_name, "", 0);
6328  build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
6329  mysql_mutex_lock(&LOCK_gdl);
6330  if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE))
6331  goto error;
6332  log_entry= part_info->first_log_entry;
6333  part_info->frm_log_entry= log_entry;
6334  if (write_execute_ddl_log_entry(log_entry->entry_pos,
6335  FALSE, &exec_log_entry))
6336  goto error;
6337  release_part_info_log_entries(old_first_log_entry);
6338  mysql_mutex_unlock(&LOCK_gdl);
6339  DBUG_RETURN(FALSE);
6340 
6341 error:
6342  release_part_info_log_entries(part_info->first_log_entry);
6343  mysql_mutex_unlock(&LOCK_gdl);
6344  part_info->first_log_entry= old_first_log_entry;
6345  part_info->frm_log_entry= NULL;
6346  my_error(ER_DDL_LOG_ERROR, MYF(0));
6347  DBUG_RETURN(TRUE);
6348 }
6349 
6350 
6351 /*
6352  Write the log entries to ensure that the drop partition command is completed
6353  even in the presence of a crash.
6354 
6355  SYNOPSIS
6356  write_log_drop_partition()
6357  lpt Struct containing parameters
6358  RETURN VALUES
6359  TRUE Error
6360  FALSE Success
6361  DESCRIPTION
6362  Prepare entries to the ddl log indicating all partitions to drop and to
6363  install the shadow frm file and remove the old frm file.
6364 */
6365 
6366 static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
6367 {
6368  partition_info *part_info= lpt->part_info;
6369  DDL_LOG_MEMORY_ENTRY *log_entry;
6370  DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
6371  char tmp_path[FN_REFLEN + 1];
6372  char path[FN_REFLEN + 1];
6373  uint next_entry= 0;
6374  DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
6375  DBUG_ENTER("write_log_drop_partition");
6376 
6377  part_info->first_log_entry= NULL;
6378  build_table_filename(path, sizeof(path) - 1, lpt->db,
6379  lpt->table_name, "", 0);
6380  build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt);
6381  mysql_mutex_lock(&LOCK_gdl);
6382  if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
6383  FALSE))
6384  goto error;
6385  if (write_log_replace_delete_frm(lpt, next_entry, (const char*)tmp_path,
6386  (const char*)path, TRUE))
6387  goto error;
6388  log_entry= part_info->first_log_entry;
6389  part_info->frm_log_entry= log_entry;
6390  if (write_execute_ddl_log_entry(log_entry->entry_pos,
6391  FALSE, &exec_log_entry))
6392  goto error;
6393  release_part_info_log_entries(old_first_log_entry);
6394  mysql_mutex_unlock(&LOCK_gdl);
6395  DBUG_RETURN(FALSE);
6396 
6397 error:
6398  release_part_info_log_entries(part_info->first_log_entry);
6399  mysql_mutex_unlock(&LOCK_gdl);
6400  part_info->first_log_entry= old_first_log_entry;
6401  part_info->frm_log_entry= NULL;
6402  my_error(ER_DDL_LOG_ERROR, MYF(0));
6403  DBUG_RETURN(TRUE);
6404 }
6405 
6406 
6407 /*
6408  Write the log entries to ensure that the add partition command is not
6409  executed at all if a crash before it has completed
6410 
6411  SYNOPSIS
6412  write_log_add_change_partition()
6413  lpt Struct containing parameters
6414  RETURN VALUES
6415  TRUE Error
6416  FALSE Success
6417  DESCRIPTION
6418  Prepare entries to the ddl log indicating all partitions to drop and to
6419  remove the shadow frm file.
6420  We always inject entries backwards in the list in the ddl log since we
6421  don't know the entry position until we have written it.
6422 */
6423 
6424 static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
6425 {
6426  partition_info *part_info= lpt->part_info;
6427  DDL_LOG_MEMORY_ENTRY *log_entry;
6428  DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
6429  char tmp_path[FN_REFLEN + 1];
6430  char path[FN_REFLEN + 1];
6431  uint next_entry= 0;
6432  DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
6433  /* write_log_drop_shadow_frm(lpt) must have been run first */
6434  DBUG_ASSERT(old_first_log_entry);
6435  DBUG_ENTER("write_log_add_change_partition");
6436 
6437  build_table_filename(path, sizeof(path) - 1, lpt->db,
6438  lpt->table_name, "", 0);
6439  build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt);
6440  mysql_mutex_lock(&LOCK_gdl);
6441 
6442  /* Relink the previous drop shadow frm entry */
6443  if (old_first_log_entry)
6444  next_entry= old_first_log_entry->entry_pos;
6445  if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
6446  FALSE))
6447  goto error;
6448  log_entry= part_info->first_log_entry;
6449 
6450  if (write_execute_ddl_log_entry(log_entry->entry_pos,
6451  FALSE,
6452  /* Reuse the old execute ddl_log_entry */
6453  &exec_log_entry))
6454  goto error;
6455  mysql_mutex_unlock(&LOCK_gdl);
6456  set_part_info_exec_log_entry(part_info, exec_log_entry);
6457  DBUG_RETURN(FALSE);
6458 
6459 error:
6460  release_part_info_log_entries(part_info->first_log_entry);
6461  mysql_mutex_unlock(&LOCK_gdl);
6462  part_info->first_log_entry= old_first_log_entry;
6463  my_error(ER_DDL_LOG_ERROR, MYF(0));
6464  DBUG_RETURN(TRUE);
6465 }
6466 
6467 
6468 /*
6469  Write description of how to complete the operation after first phase of
6470  change partitions.
6471 
6472  SYNOPSIS
6473  write_log_final_change_partition()
6474  lpt Struct containing parameters
6475  RETURN VALUES
6476  TRUE Error
6477  FALSE Success
6478  DESCRIPTION
6479  We will write log entries that specify to
6480  1) Install the shadow frm file.
6481  2) Remove all partitions reorganized. (To be able to reorganize a partition
6482  to the same name. Like in REORGANIZE p0 INTO (p0, p1),
6483  so that the later rename from the new p0-temporary name to p0 don't
6484  fail because the partition already exists.
6485  3) Rename others to reflect the new naming scheme.
6486 
6487  Note that it is written in the ddl log in reverse.
6488 */
6489 
6490 static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt)
6491 {
6492  partition_info *part_info= lpt->part_info;
6493  DDL_LOG_MEMORY_ENTRY *log_entry;
6494  DDL_LOG_MEMORY_ENTRY *exec_log_entry= part_info->exec_log_entry;
6495  char path[FN_REFLEN + 1];
6496  char shadow_path[FN_REFLEN + 1];
6497  DDL_LOG_MEMORY_ENTRY *old_first_log_entry= part_info->first_log_entry;
6498  uint next_entry= 0;
6499  DBUG_ENTER("write_log_final_change_partition");
6500 
6501  /*
6502  Do not link any previous log entry.
6503  Replace the revert operations with forced retry operations.
6504  */
6505  part_info->first_log_entry= NULL;
6506  build_table_filename(path, sizeof(path) - 1, lpt->db,
6507  lpt->table_name, "", 0);
6508  build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
6509  mysql_mutex_lock(&LOCK_gdl);
6510  if (write_log_changed_partitions(lpt, &next_entry, (const char*)path))
6511  goto error;
6512  if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
6513  lpt->alter_info->flags &
6514  Alter_info::ALTER_REORGANIZE_PARTITION))
6515  goto error;
6516  if (write_log_replace_delete_frm(lpt, next_entry, shadow_path, path, TRUE))
6517  goto error;
6518  log_entry= part_info->first_log_entry;
6519  part_info->frm_log_entry= log_entry;
6520  /* Overwrite the revert execute log entry with this retry execute entry */
6521  if (write_execute_ddl_log_entry(log_entry->entry_pos,
6522  FALSE, &exec_log_entry))
6523  goto error;
6524  release_part_info_log_entries(old_first_log_entry);
6525  mysql_mutex_unlock(&LOCK_gdl);
6526  DBUG_RETURN(FALSE);
6527 
6528 error:
6529  release_part_info_log_entries(part_info->first_log_entry);
6530  mysql_mutex_unlock(&LOCK_gdl);
6531  part_info->first_log_entry= old_first_log_entry;
6532  part_info->frm_log_entry= NULL;
6533  my_error(ER_DDL_LOG_ERROR, MYF(0));
6534  DBUG_RETURN(TRUE);
6535 }
6536 
6537 
6538 /*
6539  Remove entry from ddl log and release resources for others to use
6540 
6541  SYNOPSIS
6542  write_log_completed()
6543  lpt Struct containing parameters
6544  RETURN VALUES
6545  TRUE Error
6546  FALSE Success
6547 */
6548 
6549 static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt,
6550  bool dont_crash)
6551 {
6552  partition_info *part_info= lpt->part_info;
6553  DDL_LOG_MEMORY_ENTRY *log_entry= part_info->exec_log_entry;
6554  DBUG_ENTER("write_log_completed");
6555 
6556  DBUG_ASSERT(log_entry);
6557  mysql_mutex_lock(&LOCK_gdl);
6558  if (write_execute_ddl_log_entry(0UL, TRUE, &log_entry))
6559  {
6560  /*
6561  Failed to write, Bad...
6562  We have completed the operation but have log records to REMOVE
6563  stuff that shouldn't be removed. What clever things could one do
6564  here? An error output was written to the error output by the
6565  above method so we don't do anything here.
6566  */
6567  ;
6568  }
6569  release_part_info_log_entries(part_info->first_log_entry);
6570  release_part_info_log_entries(part_info->exec_log_entry);
6571  mysql_mutex_unlock(&LOCK_gdl);
6572  part_info->exec_log_entry= NULL;
6573  part_info->first_log_entry= NULL;
6574  DBUG_VOID_RETURN;
6575 }
6576 
6577 
6578 /*
6579  Release all log entries
6580  SYNOPSIS
6581  release_log_entries()
6582  part_info Partition info struct
6583  RETURN VALUES
6584  NONE
6585 */
6586 
6587 static void release_log_entries(partition_info *part_info)
6588 {
6589  mysql_mutex_lock(&LOCK_gdl);
6590  release_part_info_log_entries(part_info->first_log_entry);
6591  release_part_info_log_entries(part_info->exec_log_entry);
6592  mysql_mutex_unlock(&LOCK_gdl);
6593  part_info->first_log_entry= NULL;
6594  part_info->exec_log_entry= NULL;
6595 }
6596 
6597 
6598 /*
6599  Final part of partition changes to handle things when under
6600  LOCK TABLES.
6601  SYNPOSIS
6602  alter_partition_lock_handling()
6603  lpt Struct carrying parameters
6604  RETURN VALUES
6605  NONE
6606 */
6607 static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
6608 {
6609  THD *thd= lpt->thd;
6610 
6611  if (lpt->table)
6612  {
6613  /*
6614  Remove all instances of the table and its locks and other resources.
6615  */
6616  close_all_tables_for_name(thd, lpt->table->s, false, NULL);
6617  }
6618  lpt->table= 0;
6619  lpt->table_list->table= 0;
6620  if (thd->locked_tables_mode)
6621  {
6622  Diagnostics_area *stmt_da= NULL;
6623  Diagnostics_area tmp_stmt_da;
6624 
6625  if (thd->is_error())
6626  {
6627  /* reopen might fail if we have a previous error, use a temporary da. */
6628  stmt_da= thd->get_stmt_da();
6629  thd->set_stmt_da(&tmp_stmt_da);
6630  }
6631 
6632  if (thd->locked_tables_list.reopen_tables(thd))
6633  sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE");
6634 
6635  if (stmt_da)
6636  thd->set_stmt_da(stmt_da);
6637  }
6638 }
6639 
6640 
6649 static int alter_close_table(ALTER_PARTITION_PARAM_TYPE *lpt)
6650 {
6651  DBUG_ENTER("alter_close_table");
6652 
6653  if (lpt->table->db_stat)
6654  {
6655  mysql_lock_remove(lpt->thd, lpt->thd->lock, lpt->table);
6656  lpt->table->file->ha_close();
6657  lpt->table->db_stat= 0; // Mark file closed
6658  }
6659  DBUG_RETURN(0);
6660 }
6661 
6662 
6673 void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt,
6674  bool action_completed,
6675  bool drop_partition,
6676  bool frm_install,
6677  bool close_table)
6678 {
6679  partition_info *part_info= lpt->part_info;
6680  THD *thd= lpt->thd;
6681  TABLE *table= lpt->table;
6682  DBUG_ENTER("handle_alter_part_error");
6683  DBUG_ASSERT(table->m_needs_reopen);
6684 
6685  if (close_table)
6686  {
6687  /*
6688  All instances of this table needs to be closed.
6689  Better to do that here, than leave the cleaning up to others.
6690  Aquire EXCLUSIVE mdl lock if not already aquired.
6691  */
6692  if (!thd->mdl_context.is_lock_owner(MDL_key::TABLE, lpt->db,
6693  lpt->table_name,
6694  MDL_EXCLUSIVE))
6695  {
6696  if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
6697  {
6698  /* At least remove this instance on failure */
6699  goto err_exclusive_lock;
6700  }
6701  }
6702  /* Ensure the share is destroyed and reopened. */
6703  part_info= lpt->part_info->get_clone();
6704  close_all_tables_for_name(thd, table->s, false, NULL);
6705  }
6706  else
6707  {
6708 err_exclusive_lock:
6709  /*
6710  Temporarily remove it from the locked table list, so that it will get
6711  reopened.
6712  */
6713  thd->locked_tables_list.unlink_from_list(thd,
6714  table->pos_in_locked_tables,
6715  false);
6716  /*
6717  Make sure that the table is unlocked, closed and removed from
6718  the table cache.
6719  */
6720  mysql_lock_remove(thd, thd->lock, table);
6721  part_info= lpt->part_info->get_clone();
6722  close_thread_table(thd, &thd->open_tables);
6723  lpt->table_list->table= NULL;
6724  }
6725 
6726  if (part_info->first_log_entry &&
6727  execute_ddl_log_entry(thd, part_info->first_log_entry->entry_pos))
6728  {
6729  /*
6730  We couldn't recover from error, most likely manual interaction
6731  is required.
6732  */
6733  write_log_completed(lpt, FALSE);
6734  release_log_entries(part_info);
6735  if (!action_completed)
6736  {
6737  if (drop_partition)
6738  {
6739  /* Table is still ok, but we left a shadow frm file behind. */
6740  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, 1,
6741  "%s %s",
6742  "Operation was unsuccessful, table is still intact,",
6743  "but it is possible that a shadow frm file was left behind");
6744  }
6745  else
6746  {
6747  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, 1,
6748  "%s %s %s %s",
6749  "Operation was unsuccessful, table is still intact,",
6750  "but it is possible that a shadow frm file was left behind.",
6751  "It is also possible that temporary partitions are left behind,",
6752  "these could be empty or more or less filled with records");
6753  }
6754  }
6755  else
6756  {
6757  if (frm_install)
6758  {
6759  /*
6760  Failed during install of shadow frm file, table isn't intact
6761  and dropped partitions are still there
6762  */
6763  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, 1,
6764  "%s %s %s",
6765  "Failed during alter of partitions, table is no longer intact.",
6766  "The frm file is in an unknown state, and a backup",
6767  "is required.");
6768  }
6769  else if (drop_partition)
6770  {
6771  /*
6772  Table is ok, we have switched to new table but left dropped
6773  partitions still in their places. We remove the log records and
6774  ask the user to perform the action manually. We remove the log
6775  records and ask the user to perform the action manually.
6776  */
6777  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, 1,
6778  "%s %s",
6779  "Failed during drop of partitions, table is intact.",
6780  "Manual drop of remaining partitions is required");
6781  }
6782  else
6783  {
6784  /*
6785  We failed during renaming of partitions. The table is most
6786  certainly in a very bad state so we give user warning and disable
6787  the table by writing an ancient frm version into it.
6788  */
6789  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, 1,
6790  "%s %s %s",
6791  "Failed during renaming of partitions. We are now in a position",
6792  "where table is not reusable",
6793  "Table is disabled by writing ancient frm file version into it");
6794  }
6795  }
6796  }
6797  else
6798  {
6799  release_log_entries(part_info);
6800  if (!action_completed)
6801  {
6802  /*
6803  We hit an error before things were completed but managed
6804  to recover from the error. An error occurred and we have
6805  restored things to original so no need for further action.
6806  */
6807  ;
6808  }
6809  else
6810  {
6811  /*
6812  We hit an error after we had completed most of the operation
6813  and were successful in a second attempt so the operation
6814  actually is successful now. We need to issue a warning that
6815  even though we reported an error the operation was successfully
6816  completed.
6817  */
6818  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, 1,"%s %s",
6819  "Operation was successfully completed by failure handling,",
6820  "after failure of normal operation");
6821  }
6822  }
6823 
6824  if (thd->locked_tables_mode)
6825  {
6826  Diagnostics_area *stmt_da= NULL;
6827  Diagnostics_area tmp_stmt_da;
6828 
6829  if (thd->is_error())
6830  {
6831  /* reopen might fail if we have a previous error, use a temporary da. */
6832  stmt_da= thd->get_stmt_da();
6833  thd->set_stmt_da(&tmp_stmt_da);
6834  }
6835 
6836  if (thd->locked_tables_list.reopen_tables(thd))
6837  sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE");
6838 
6839  if (stmt_da)
6840  thd->set_stmt_da(stmt_da);
6841  }
6842 
6843  DBUG_VOID_RETURN;
6844 }
6845 
6846 
6855 static void downgrade_mdl_if_lock_tables_mode(THD *thd, MDL_ticket *ticket,
6856  enum_mdl_type type)
6857 {
6858  if (thd->locked_tables_mode)
6859  ticket->downgrade_lock(type);
6860 }
6861 
6862 
6884 uint fast_alter_partition_table(THD *thd, TABLE *table,
6885  Alter_info *alter_info,
6886  HA_CREATE_INFO *create_info,
6887  TABLE_LIST *table_list,
6888  char *db,
6889  const char *table_name)
6890 {
6891  /* Set-up struct used to write frm files */
6892  partition_info *part_info;
6894  ALTER_PARTITION_PARAM_TYPE *lpt= &lpt_obj;
6895  bool action_completed= FALSE;
6896  bool close_table_on_failure= FALSE;
6897  bool frm_install= FALSE;
6898  MDL_ticket *mdl_ticket= table->mdl_ticket;
6899  DBUG_ENTER("fast_alter_partition_table");
6900  DBUG_ASSERT(table->m_needs_reopen);
6901 
6902  part_info= table->part_info;
6903  lpt->thd= thd;
6904  lpt->table_list= table_list;
6905  lpt->part_info= part_info;
6906  lpt->alter_info= alter_info;
6907  lpt->create_info= create_info;
6908  lpt->db_options= create_info->table_options;
6909  if (create_info->row_type == ROW_TYPE_DYNAMIC)
6910  lpt->db_options|= HA_OPTION_PACK_RECORD;
6911  lpt->table= table;
6912  lpt->key_info_buffer= 0;
6913  lpt->key_count= 0;
6914  lpt->db= db;
6915  lpt->table_name= table_name;
6916  lpt->copied= 0;
6917  lpt->deleted= 0;
6918  lpt->pack_frm_data= NULL;
6919  lpt->pack_frm_len= 0;
6920 
6921  if (table->file->alter_table_flags(alter_info->flags) &
6922  HA_PARTITION_ONE_PHASE)
6923  {
6924  /*
6925  In the case where the engine supports one phase online partition
6926  changes it is not necessary to have any exclusive locks. The
6927  correctness is upheld instead by transactions being aborted if they
6928  access the table after its partition definition has changed (if they
6929  are still using the old partition definition).
6930 
6931  The handler is in this case responsible to ensure that all users
6932  start using the new frm file after it has changed. To implement
6933  one phase it is necessary for the handler to have the master copy
6934  of the frm file and use discovery mechanisms to renew it. Thus
6935  write frm will write the frm, pack the new frm and finally
6936  the frm is deleted and the discovery mechanisms will either restore
6937  back to the old or installing the new after the change is activated.
6938 
6939  Thus all open tables will be discovered that they are old, if not
6940  earlier as soon as they try an operation using the old table. One
6941  should ensure that this is checked already when opening a table,
6942  even if it is found in the cache of open tables.
6943 
6944  change_partitions will perform all operations and it is the duty of
6945  the handler to ensure that the frm files in the system gets updated
6946  in synch with the changes made and if an error occurs that a proper
6947  error handling is done.
6948 
6949  If the MySQL Server crashes at this moment but the handler succeeds
6950  in performing the change then the binlog is not written for the
6951  change. There is no way to solve this as long as the binlog is not
6952  transactional and even then it is hard to solve it completely.
6953 
6954  The first approach here was to downgrade locks. Now a different approach
6955  is decided upon. The idea is that the handler will have access to the
6956  Alter_info when store_lock arrives with TL_WRITE_ALLOW_READ. So if the
6957  handler knows that this functionality can be handled with a lower lock
6958  level it will set the lock level to TL_WRITE_ALLOW_WRITE immediately.
6959  Thus the need to downgrade the lock disappears.
6960  1) Write the new frm, pack it and then delete it
6961  2) Perform the change within the handler
6962  */
6963  if (mysql_write_frm(lpt, WFRM_WRITE_SHADOW | WFRM_PACK_FRM) ||
6964  mysql_change_partitions(lpt))
6965  {
6966  goto err;
6967  }
6968  }
6969  else if (alter_info->flags & Alter_info::ALTER_DROP_PARTITION)
6970  {
6971  /*
6972  Now after all checks and setting state on dropped partitions we can
6973  start the actual dropping of the partitions.
6974 
6975  Drop partition is actually two things happening. The first is that
6976  a lot of records are deleted. The second is that the behaviour of
6977  subsequent updates and writes and deletes will change. The delete
6978  part can be handled without any particular high lock level by
6979  transactional engines whereas non-transactional engines need to
6980  ensure that this change is done with an exclusive lock on the table.
6981  The second part, the change of partitioning does however require
6982  an exclusive lock to install the new partitioning as one atomic
6983  operation. If this is not the case, it is possible for two
6984  transactions to see the change in a different order than their
6985  serialisation order. Thus we need an exclusive lock for both
6986  transactional and non-transactional engines.
6987 
6988  For LIST partitions it could be possible to avoid the exclusive lock
6989  (and for RANGE partitions if they didn't rearrange range definitions
6990  after a DROP PARTITION) if one ensured that failed accesses to the
6991  dropped partitions was aborted for sure (thus only possible for
6992  transactional engines).
6993 
6994  0) Write an entry that removes the shadow frm file if crash occurs
6995  1) Write the new frm file as a shadow frm
6996  2) Get an exclusive metadata lock on the table (waits for all active
6997  transactions using this table). This ensures that we
6998  can release all other locks on the table and since no one can open
6999  the table, there can be no new threads accessing the table. They
7000  will be hanging on this exclusive lock.
7001  3) Write the ddl log to ensure that the operation is completed
7002  even in the presence of a MySQL Server crash (the log is executed
7003  before any other threads are started, so there are no locking issues).
7004  4) Close the table that have already been opened but didn't stumble on
7005  the abort locked previously. This is done as part of the
7006  alter_close_table call.
7007  5) Write the bin log
7008  Unfortunately the writing of the binlog is not synchronised with
7009  other logging activities. So no matter in which order the binlog
7010  is written compared to other activities there will always be cases
7011  where crashes make strange things occur. In this placement it can
7012  happen that the ALTER TABLE DROP PARTITION gets performed in the
7013  master but not in the slaves if we have a crash, after writing the
7014  ddl log but before writing the binlog. A solution to this would
7015  require writing the statement first in the ddl log and then
7016  when recovering from the crash read the binlog and insert it into
7017  the binlog if not written already.
7018  6) Install the previously written shadow frm file
7019  7) Prepare handlers for drop of partitions
7020  8) Drop the partitions
7021  9) Remove entries from ddl log
7022  10) Reopen table if under lock tables
7023  11) Complete query
7024 
7025  We insert Error injections at all places where it could be interesting
7026  to test if recovery is properly done.
7027  */
7028  if (write_log_drop_shadow_frm(lpt) ||
7029  ERROR_INJECT_CRASH("crash_drop_partition_1") ||
7030  ERROR_INJECT_ERROR("fail_drop_partition_1") ||
7031  mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
7032  ERROR_INJECT_CRASH("crash_drop_partition_2") ||
7033  ERROR_INJECT_ERROR("fail_drop_partition_2") ||
7034  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN) ||
7035  ERROR_INJECT_CRASH("crash_drop_partition_3") ||
7036  ERROR_INJECT_ERROR("fail_drop_partition_3") ||
7037  (close_table_on_failure= TRUE, FALSE) ||
7038  write_log_drop_partition(lpt) ||
7039  (action_completed= TRUE, FALSE) ||
7040  ERROR_INJECT_CRASH("crash_drop_partition_4") ||
7041  ERROR_INJECT_ERROR("fail_drop_partition_4") ||
7042  alter_close_table(lpt) ||
7043  (close_table_on_failure= FALSE, FALSE) ||
7044  ERROR_INJECT_CRASH("crash_drop_partition_5") ||
7045  ERROR_INJECT_ERROR("fail_drop_partition_5") ||
7046  ((!thd->lex->no_write_to_binlog) &&
7047  (write_bin_log(thd, FALSE,
7048  thd->query(), thd->query_length()), FALSE)) ||
7049  ERROR_INJECT_CRASH("crash_drop_partition_6") ||
7050  ERROR_INJECT_ERROR("fail_drop_partition_6") ||
7051  (frm_install= TRUE, FALSE) ||
7052  mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
7053  (frm_install= FALSE, FALSE) ||
7054  ERROR_INJECT_CRASH("crash_drop_partition_7") ||
7055  ERROR_INJECT_ERROR("fail_drop_partition_7") ||
7056  mysql_drop_partitions(lpt) ||
7057  ERROR_INJECT_CRASH("crash_drop_partition_8") ||
7058  ERROR_INJECT_ERROR("fail_drop_partition_8") ||
7059  (write_log_completed(lpt, FALSE), FALSE) ||
7060  ERROR_INJECT_CRASH("crash_drop_partition_9") ||
7061  ERROR_INJECT_ERROR("fail_drop_partition_9") ||
7062  (alter_partition_lock_handling(lpt), FALSE))
7063  {
7064  handle_alter_part_error(lpt, action_completed, TRUE, frm_install,
7065  close_table_on_failure);
7066  goto err;
7067  }
7068  }
7069  else if ((alter_info->flags & Alter_info::ALTER_ADD_PARTITION) &&
7070  (part_info->part_type == RANGE_PARTITION ||
7071  part_info->part_type == LIST_PARTITION))
7072  {
7073  /*
7074  ADD RANGE/LIST PARTITIONS
7075  In this case there are no tuples removed and no tuples are added.
7076  Thus the operation is merely adding a new partition. Thus it is
7077  necessary to perform the change as an atomic operation. Otherwise
7078  someone reading without seeing the new partition could potentially
7079  miss updates made by a transaction serialised before it that are
7080  inserted into the new partition.
7081 
7082  0) Write an entry that removes the shadow frm file if crash occurs
7083  1) Write the new frm file as a shadow frm file
7084  2) Get an exclusive metadata lock on the table (waits for all active
7085  transactions using this table). This ensures that we
7086  can release all other locks on the table and since no one can open
7087  the table, there can be no new threads accessing the table. They
7088  will be hanging on this exclusive lock.
7089  3) Write an entry to remove the new parttions if crash occurs
7090  4) Add the new partitions.
7091  5) Close all instances of the table and remove them from the table cache.
7092  6) Write binlog
7093  7) Now the change is completed except for the installation of the
7094  new frm file. We thus write an action in the log to change to
7095  the shadow frm file
7096  8) Install the new frm file of the table where the partitions are
7097  added to the table.
7098  9) Remove entries from ddl log
7099  10)Reopen tables if under lock tables
7100  11)Complete query
7101  */
7102  if (write_log_drop_shadow_frm(lpt) ||
7103  ERROR_INJECT_CRASH("crash_add_partition_1") ||
7104  ERROR_INJECT_ERROR("fail_add_partition_1") ||
7105  mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
7106  ERROR_INJECT_CRASH("crash_add_partition_2") ||
7107  ERROR_INJECT_ERROR("fail_add_partition_2") ||
7108  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN) ||
7109  ERROR_INJECT_CRASH("crash_add_partition_3") ||
7110  ERROR_INJECT_ERROR("fail_add_partition_3") ||
7111  (close_table_on_failure= TRUE, FALSE) ||
7112  write_log_add_change_partition(lpt) ||
7113  ERROR_INJECT_CRASH("crash_add_partition_4") ||
7114  ERROR_INJECT_ERROR("fail_add_partition_4") ||
7115  mysql_change_partitions(lpt) ||
7116  ERROR_INJECT_CRASH("crash_add_partition_5") ||
7117  ERROR_INJECT_ERROR("fail_add_partition_5") ||
7118  (close_table_on_failure= FALSE, FALSE) ||
7119  alter_close_table(lpt) ||
7120  ERROR_INJECT_CRASH("crash_add_partition_6") ||
7121  ERROR_INJECT_ERROR("fail_add_partition_6") ||
7122  ((!thd->lex->no_write_to_binlog) &&
7123  (write_bin_log(thd, FALSE,
7124  thd->query(), thd->query_length()), FALSE)) ||
7125  ERROR_INJECT_CRASH("crash_add_partition_7") ||
7126  ERROR_INJECT_ERROR("fail_add_partition_7") ||
7127  write_log_rename_frm(lpt) ||
7128  (action_completed= TRUE, FALSE) ||
7129  ERROR_INJECT_CRASH("crash_add_partition_8") ||
7130  ERROR_INJECT_ERROR("fail_add_partition_8") ||
7131  (frm_install= TRUE, FALSE) ||
7132  mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
7133  (frm_install= FALSE, FALSE) ||
7134  ERROR_INJECT_CRASH("crash_add_partition_9") ||
7135  ERROR_INJECT_ERROR("fail_add_partition_9") ||
7136  (write_log_completed(lpt, FALSE), FALSE) ||
7137  ERROR_INJECT_CRASH("crash_add_partition_10") ||
7138  ERROR_INJECT_ERROR("fail_add_partition_10") ||
7139  (alter_partition_lock_handling(lpt), FALSE))
7140  {
7141  handle_alter_part_error(lpt, action_completed, FALSE, frm_install,
7142  close_table_on_failure);
7143  goto err;
7144  }
7145  }
7146  else
7147  {
7148  /*
7149  ADD HASH PARTITION/
7150  COALESCE PARTITION/
7151  REBUILD PARTITION/
7152  REORGANIZE PARTITION
7153 
7154  In this case all records are still around after the change although
7155  possibly organised into new partitions, thus by ensuring that all
7156  updates go to both the old and the new partitioning scheme we can
7157  actually perform this operation lock-free. The only exception to
7158  this is when REORGANIZE PARTITION adds/drops ranges. In this case
7159  there needs to be an exclusive lock during the time when the range
7160  changes occur.
7161  This is only possible if the handler can ensure double-write for a
7162  period. The double write will ensure that it doesn't matter where the
7163  data is read from since both places are updated for writes. If such
7164  double writing is not performed then it is necessary to perform the
7165  change with the usual exclusive lock. With double writes it is even
7166  possible to perform writes in parallel with the reorganisation of
7167  partitions.
7168 
7169  Without double write procedure we get the following procedure.
7170  The only difference with using double write is that we can downgrade
7171  the lock to TL_WRITE_ALLOW_WRITE. Double write in this case only
7172  double writes from old to new. If we had double writing in both
7173  directions we could perform the change completely without exclusive
7174  lock for HASH partitions.
7175  Handlers that perform double writing during the copy phase can actually
7176  use a lower lock level. This can be handled inside store_lock in the
7177  respective handler.
7178 
7179  0) Write an entry that removes the shadow frm file if crash occurs.
7180  1) Write the shadow frm file of new partitioning.
7181  2) Log such that temporary partitions added in change phase are
7182  removed in a crash situation.
7183  3) Add the new partitions.
7184  Copy from the reorganised partitions to the new partitions.
7185  4) Get an exclusive metadata lock on the table (waits for all active
7186  transactions using this table). This ensures that we
7187  can release all other locks on the table and since no one can open
7188  the table, there can be no new threads accessing the table. They
7189  will be hanging on this exclusive lock.
7190  5) Close the table.
7191  6) Log that operation is completed and log all complete actions
7192  needed to complete operation from here.
7193  7) Write bin log.
7194  8) Prepare handlers for rename and delete of partitions.
7195  9) Rename and drop the reorged partitions such that they are no
7196  longer used and rename those added to their real new names.
7197  10) Install the shadow frm file.
7198  11) Reopen the table if under lock tables.
7199  12) Complete query.
7200  */
7201  if (write_log_drop_shadow_frm(lpt) ||
7202  ERROR_INJECT_CRASH("crash_change_partition_1") ||
7203  ERROR_INJECT_ERROR("fail_change_partition_1") ||
7204  mysql_write_frm(lpt, WFRM_WRITE_SHADOW) ||
7205  ERROR_INJECT_CRASH("crash_change_partition_2") ||
7206  ERROR_INJECT_ERROR("fail_change_partition_2") ||
7207  (close_table_on_failure= TRUE, FALSE) ||
7208  write_log_add_change_partition(lpt) ||
7209  ERROR_INJECT_CRASH("crash_change_partition_3") ||
7210  ERROR_INJECT_ERROR("fail_change_partition_3") ||
7211  mysql_change_partitions(lpt) ||
7212  ERROR_INJECT_CRASH("crash_change_partition_4") ||
7213  ERROR_INJECT_ERROR("fail_change_partition_4") ||
7214  wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN) ||
7215  ERROR_INJECT_CRASH("crash_change_partition_5") ||
7216  ERROR_INJECT_ERROR("fail_change_partition_5") ||
7217  alter_close_table(lpt) ||
7218  (close_table_on_failure= FALSE, FALSE) ||
7219  ERROR_INJECT_CRASH("crash_change_partition_6") ||
7220  ERROR_INJECT_ERROR("fail_change_partition_6") ||
7221  write_log_final_change_partition(lpt) ||
7222  (action_completed= TRUE, FALSE) ||
7223  ERROR_INJECT_CRASH("crash_change_partition_7") ||
7224  ERROR_INJECT_ERROR("fail_change_partition_7") ||
7225  ((!thd->lex->no_write_to_binlog) &&
7226  (write_bin_log(thd, FALSE,
7227  thd->query(), thd->query_length()), FALSE)) ||
7228  ERROR_INJECT_CRASH("crash_change_partition_8") ||
7229  ERROR_INJECT_ERROR("fail_change_partition_8") ||
7230  ((frm_install= TRUE), FALSE) ||
7231  mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) ||
7232  (frm_install= FALSE, FALSE) ||
7233  ERROR_INJECT_CRASH("crash_change_partition_9") ||
7234  ERROR_INJECT_ERROR("fail_change_partition_9") ||
7235  mysql_drop_partitions(lpt) ||
7236  ERROR_INJECT_CRASH("crash_change_partition_10") ||
7237  ERROR_INJECT_ERROR("fail_change_partition_10") ||
7238  mysql_rename_partitions(lpt) ||
7239  ERROR_INJECT_CRASH("crash_change_partition_11") ||
7240  ERROR_INJECT_ERROR("fail_change_partition_11") ||
7241  (write_log_completed(lpt, FALSE), FALSE) ||
7242  ERROR_INJECT_CRASH("crash_change_partition_12") ||
7243  ERROR_INJECT_ERROR("fail_change_partition_12") ||
7244  (alter_partition_lock_handling(lpt), FALSE))
7245  {
7246  handle_alter_part_error(lpt, action_completed, FALSE, frm_install,
7247  close_table_on_failure);
7248  goto err;
7249  }
7250  }
7251  downgrade_mdl_if_lock_tables_mode(thd, mdl_ticket, MDL_SHARED_NO_READ_WRITE);
7252  /*
7253  A final step is to write the query to the binlog and send ok to the
7254  user
7255  */
7256  DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted, table_list));
7257 err:
7258  downgrade_mdl_if_lock_tables_mode(thd, mdl_ticket, MDL_SHARED_NO_READ_WRITE);
7259  DBUG_RETURN(TRUE);
7260 }
7261 #endif
7262 
7263 
7264 /*
7265  Prepare for calling val_int on partition function by setting fields to
7266  point to the record where the values of the PF-fields are stored.
7267 
7268  SYNOPSIS
7269  set_field_ptr()
7270  ptr Array of fields to change ptr
7271  new_buf New record pointer
7272  old_buf Old record pointer
7273 
7274  DESCRIPTION
7275  Set ptr in field objects of field array to refer to new_buf record
7276  instead of previously old_buf. Used before calling val_int and after
7277  it is used to restore pointers to table->record[0].
7278  This routine is placed outside of partition code since it can be useful
7279  also for other programs.
7280 */
7281 
7282 void set_field_ptr(Field **ptr, const uchar *new_buf,
7283  const uchar *old_buf)
7284 {
7285  my_ptrdiff_t diff= (new_buf - old_buf);
7286  DBUG_ENTER("set_field_ptr");
7287 
7288  do
7289  {
7290  (*ptr)->move_field_offset(diff);
7291  } while (*(++ptr));
7292  DBUG_VOID_RETURN;
7293 }
7294 
7295 
7296 /*
7297  Prepare for calling val_int on partition function by setting fields to
7298  point to the record where the values of the PF-fields are stored.
7299  This variant works on a key_part reference.
7300  It is not required that all fields are NOT NULL fields.
7301 
7302  SYNOPSIS
7303  set_key_field_ptr()
7304  key_info key info with a set of fields to change ptr
7305  new_buf New record pointer
7306  old_buf Old record pointer
7307 
7308  DESCRIPTION
7309  Set ptr in field objects of field array to refer to new_buf record
7310  instead of previously old_buf. Used before calling val_int and after
7311  it is used to restore pointers to table->record[0].
7312  This routine is placed outside of partition code since it can be useful
7313  also for other programs.
7314 */
7315 
7316 void set_key_field_ptr(KEY *key_info, const uchar *new_buf,
7317  const uchar *old_buf)
7318 {
7319  KEY_PART_INFO *key_part= key_info->key_part;
7320  uint key_parts= key_info->user_defined_key_parts;
7321  uint i= 0;
7322  my_ptrdiff_t diff= (new_buf - old_buf);
7323  DBUG_ENTER("set_key_field_ptr");
7324 
7325  do
7326  {
7327  key_part->field->move_field_offset(diff);
7328  key_part++;
7329  } while (++i < key_parts);
7330  DBUG_VOID_RETURN;
7331 }
7332 
7333 
7334 /*
7335  SYNOPSIS
7336  mem_alloc_error()
7337  size Size of memory attempted to allocate
7338  None
7339 
7340  RETURN VALUES
7341  None
7342 
7343  DESCRIPTION
7344  A routine to use for all the many places in the code where memory
7345  allocation error can happen, a tremendous amount of them, needs
7346  simple routine that signals this error.
7347 */
7348 
7349 void mem_alloc_error(size_t size)
7350 {
7351  my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
7352  static_cast<int>(size));
7353 }
7354 
7355 #ifdef WITH_PARTITION_STORAGE_ENGINE
7356 
7371 bool make_used_partitions_str(partition_info *part_info,
7372  List<const char> *parts)
7373 {
7374  parts->empty();
7375  partition_element *pe;
7376  uint partition_id= 0;
7377  List_iterator<partition_element> it(part_info->partitions);
7378  StringBuffer<FN_LEN> part_str(system_charset_info);
7379 
7380  if (part_info->is_sub_partitioned())
7381  {
7382  partition_element *head_pe;
7383  while ((head_pe= it++))
7384  {
7385  List_iterator<partition_element> it2(head_pe->subpartitions);
7386  while ((pe= it2++))
7387  {
7388  if (bitmap_is_set(&part_info->read_partitions, partition_id))
7389  {
7390  part_str.length(0);
7391  if ((part_str.append(head_pe->partition_name,
7392  strlen(head_pe->partition_name),
7393  system_charset_info)) ||
7394  part_str.append('_') ||
7395  part_str.append(pe->partition_name,
7396  strlen(pe->partition_name),
7397  system_charset_info) ||
7398  parts->push_back(part_str.dup(current_thd->mem_root)))
7399  return true;
7400  }
7401  partition_id++;
7402  }
7403  }
7404  }
7405  else
7406  {
7407  while ((pe= it++))
7408  {
7409  if (bitmap_is_set(&part_info->read_partitions, partition_id))
7410  {
7411  part_str.length(0);
7412  if (part_str.append(pe->partition_name, strlen(pe->partition_name),
7413  system_charset_info) ||
7414  parts->push_back(part_str.dup(current_thd->mem_root)))
7415  return true;
7416  }
7417  partition_id++;
7418  }
7419  }
7420  return false;
7421 }
7422 #endif
7423 
7424 /****************************************************************************
7425  * Partition interval analysis support
7426  ***************************************************************************/
7427 
7428 /*
7429  Setup partition_info::* members related to partitioning range analysis
7430 
7431  SYNOPSIS
7432  set_up_partition_func_pointers()
7433  part_info Partitioning info structure
7434 
7435  DESCRIPTION
7436  Assuming that passed partition_info structure already has correct values
7437  for members that specify [sub]partitioning type, table fields, and
7438  functions, set up partition_info::* members that are related to
7439  Partitioning Interval Analysis (see get_partitions_in_range_iter for its
7440  definition)
7441 
7442  IMPLEMENTATION
7443  There are three available interval analyzer functions:
7444  (1) get_part_iter_for_interval_via_mapping
7445  (2) get_part_iter_for_interval_cols_via_map
7446  (3) get_part_iter_for_interval_via_walking
7447 
7448  They all have limited applicability:
7449  (1) is applicable for "PARTITION BY <RANGE|LIST>(func(t.field))", where
7450  func is a monotonic function.
7451 
7452  (2) is applicable for "PARTITION BY <RANGE|LIST> COLUMNS (field_list)
7453 
7454  (3) is applicable for
7455  "[SUB]PARTITION BY <any-partitioning-type>(any_func(t.integer_field))"
7456 
7457  If both (1) and (3) are applicable, (1) is preferred over (3).
7458 
7459  This function sets part_info::get_part_iter_for_interval according to
7460  this criteria, and also sets some auxilary fields that the function
7461  uses.
7462 */
7463 #ifdef WITH_PARTITION_STORAGE_ENGINE
7464 static void set_up_range_analysis_info(partition_info *part_info)
7465 {
7466  /* Set the catch-all default */
7467  part_info->get_part_iter_for_interval= NULL;
7468  part_info->get_subpart_iter_for_interval= NULL;
7469 
7470  /*
7471  Check if get_part_iter_for_interval_via_mapping() can be used for
7472  partitioning
7473  */
7474  switch (part_info->part_type) {
7475  case RANGE_PARTITION:
7476  case LIST_PARTITION:
7477  if (!part_info->column_list)
7478  {
7479  if (part_info->part_expr->get_monotonicity_info() != NON_MONOTONIC)
7480  {
7481  part_info->get_part_iter_for_interval=
7482  get_part_iter_for_interval_via_mapping;
7483  goto setup_subparts;
7484  }
7485  }
7486  else
7487  {
7488  part_info->get_part_iter_for_interval=
7489  get_part_iter_for_interval_cols_via_map;
7490  goto setup_subparts;
7491  }
7492  default:
7493  ;
7494  }
7495 
7496  /*
7497  Check if get_part_iter_for_interval_via_walking() can be used for
7498  partitioning
7499  */
7500  if (part_info->num_part_fields == 1)
7501  {
7502  Field *field= part_info->part_field_array[0];
7503  switch (field->type()) {
7504  case MYSQL_TYPE_TINY:
7505  case MYSQL_TYPE_SHORT:
7506  case MYSQL_TYPE_INT24:
7507  case MYSQL_TYPE_LONG:
7508  case MYSQL_TYPE_LONGLONG:
7509  part_info->get_part_iter_for_interval=
7510  get_part_iter_for_interval_via_walking;
7511  break;
7512  default:
7513  ;
7514  }
7515  }
7516 
7517 setup_subparts:
7518  /*
7519  Check if get_part_iter_for_interval_via_walking() can be used for
7520  subpartitioning
7521  */
7522  if (part_info->num_subpart_fields == 1)
7523  {
7524  Field *field= part_info->subpart_field_array[0];
7525  switch (field->type()) {
7526  case MYSQL_TYPE_TINY:
7527  case MYSQL_TYPE_SHORT:
7528  case MYSQL_TYPE_LONG:
7529  case MYSQL_TYPE_LONGLONG:
7530  part_info->get_subpart_iter_for_interval=
7531  get_part_iter_for_interval_via_walking;
7532  break;
7533  default:
7534  ;
7535  }
7536  }
7537 }
7538 
7539 
7540 /*
7541  This function takes a memory of packed fields in opt-range format
7542  and stores it in record format. To avoid having to worry about how
7543  the length of fields are calculated in opt-range format we send
7544  an array of lengths used for each field in store_length_array.
7545 
7546  SYNOPSIS
7547  store_tuple_to_record()
7548  pfield Field array
7549  store_length_array Array of field lengths
7550  value Memory where fields are stored
7551  value_end End of memory
7552 
7553  RETURN VALUE
7554  nparts Number of fields assigned
7555 */
7556 uint32 store_tuple_to_record(Field **pfield,
7557  uint32 *store_length_array,
7558  uchar *value,
7559  uchar *value_end)
7560 {
7561  /* This function is inspired by store_key_image_rec. */
7562  uint32 nparts= 0;
7563  uchar *loc_value;
7564  while (value < value_end)
7565  {
7566  loc_value= value;
7567  if ((*pfield)->real_maybe_null())
7568  {
7569  if (*loc_value)
7570  (*pfield)->set_null();
7571  else
7572  (*pfield)->set_notnull();
7573  loc_value++;
7574  }
7575  uint len= (*pfield)->pack_length();
7576  (*pfield)->set_key_image(loc_value, len);
7577  value+= *store_length_array;
7578  store_length_array++;
7579  nparts++;
7580  pfield++;
7581  }
7582  return nparts;
7583 }
7584 
7598 static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec)
7599 {
7600  partition_info *part_info= val->part_info;
7601  Field **field= part_info->part_field_array;
7602  Field **fields_end= field + nvals_in_rec;
7603  int res;
7604 
7605  for (; field != fields_end; field++, val++)
7606  {
7607  if (val->max_value)
7608  return -1;
7609  if ((*field)->is_null())
7610  {
7611  if (val->null_value)
7612  continue;
7613  return -1;
7614  }
7615  if (val->null_value)
7616  return +1;
7617  res= (*field)->cmp((const uchar*)val->column_value);
7618  if (res)
7619  return res;
7620  }
7621  return 0;
7622 }
7623 
7624 
7642 static int cmp_rec_and_tuple_prune(part_column_list_val *val,
7643  uint32 n_vals_in_rec,
7644  bool is_left_endpoint,
7645  bool include_endpoint)
7646 {
7647  int cmp;
7648  Field **field;
7649  if ((cmp= cmp_rec_and_tuple(val, n_vals_in_rec)))
7650  return cmp;
7651  field= val->part_info->part_field_array + n_vals_in_rec;
7652  if (!(*field))
7653  {
7654  /*
7655  Full match, if right endpoint and not including the endpoint,
7656  (rec < part) return lesser.
7657  */
7658  if (!is_left_endpoint && !include_endpoint)
7659  return -4;
7660 
7661  /* Otherwise they are equal! */
7662  return 0;
7663  }
7664  /*
7665  The prefix is equal and there are more partition columns to compare.
7666 
7667  If including left endpoint or not including right endpoint
7668  then the record is considered lesser compared to the partition.
7669 
7670  i.e:
7671  part(10, x) <= rec(10, unknown) and rec(10, unknown) < part(10, x)
7672  part <= rec -> lesser (i.e. this or previous partitions)
7673  rec < part -> lesser (i.e. this or previous partitions)
7674  */
7675  if (is_left_endpoint == include_endpoint)
7676  return -2;
7677 
7678  /*
7679  If right endpoint and the first additional partition value
7680  is MAXVALUE, then the record is lesser.
7681  */
7682  if (!is_left_endpoint && (val + n_vals_in_rec)->max_value)
7683  return -3;
7684 
7685  /*
7686  Otherwise the record is considered greater.
7687 
7688  rec <= part -> greater (i.e. does not match this partition, seek higher).
7689  part < rec -> greater (i.e. does not match this partition, seek higher).
7690  */
7691  return 2;
7692 }
7693 
7694 
7695 typedef uint32 (*get_endpoint_func)(partition_info*, bool left_endpoint,
7696  bool include_endpoint);
7697 
7698 typedef uint32 (*get_col_endpoint_func)(partition_info*, bool left_endpoint,
7699  bool include_endpoint,
7700  uint32 num_parts);
7701 
7716 uint32 get_partition_id_cols_range_for_endpoint(partition_info *part_info,
7717  bool is_left_endpoint,
7718  bool include_endpoint,
7719  uint32 nparts)
7720 {
7721  uint min_part_id= 0, max_part_id= part_info->num_parts, loc_part_id;
7722  part_column_list_val *range_col_array= part_info->range_col_array;
7723  uint num_columns= part_info->part_field_list.elements;
7724  DBUG_ENTER("get_partition_id_cols_range_for_endpoint");
7725 
7726  /* Find the matching partition (including taking endpoint into account). */
7727  do
7728  {
7729  /* Midpoint, adjusted down, so it can never be > last partition. */
7730  loc_part_id= (max_part_id + min_part_id) >> 1;
7731  if (0 <= cmp_rec_and_tuple_prune(range_col_array +
7732  loc_part_id * num_columns,
7733  nparts,
7734  is_left_endpoint,
7735  include_endpoint))
7736  min_part_id= loc_part_id + 1;
7737  else
7738  max_part_id= loc_part_id;
7739  } while (max_part_id > min_part_id);
7740  loc_part_id= max_part_id;
7741 
7742  /* Given value must be LESS THAN the found partition. */
7743  DBUG_ASSERT(loc_part_id == part_info->num_parts ||
7744  (0 > cmp_rec_and_tuple_prune(range_col_array +
7745  loc_part_id * num_columns,
7746  nparts, is_left_endpoint,
7747  include_endpoint)));
7748  /* Given value must be GREATER THAN or EQUAL to the previous partition. */
7749  DBUG_ASSERT(loc_part_id == 0 ||
7750  (0 <= cmp_rec_and_tuple_prune(range_col_array +
7751  (loc_part_id - 1) * num_columns,
7752  nparts, is_left_endpoint,
7753  include_endpoint)));
7754 
7755  if (!is_left_endpoint)
7756  {
7757  /* Set the end after this partition if not already after the last. */
7758  if (loc_part_id < part_info->num_parts)
7759  loc_part_id++;
7760  }
7761  DBUG_RETURN(loc_part_id);
7762 }
7763 
7764 
7765 int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
7766  bool is_subpart,
7767  uint32 *store_length_array,
7768  uchar *min_value, uchar *max_value,
7769  uint min_len, uint max_len,
7770  uint flags,
7771  PARTITION_ITERATOR *part_iter)
7772 {
7773  uint32 nparts;
7774  get_col_endpoint_func get_col_endpoint;
7775  DBUG_ENTER("get_part_iter_for_interval_cols_via_map");
7776 
7777  if (part_info->part_type == RANGE_PARTITION)
7778  {
7779  get_col_endpoint= get_partition_id_cols_range_for_endpoint;
7780  part_iter->get_next= get_next_partition_id_range;
7781  }
7782  else if (part_info->part_type == LIST_PARTITION)
7783  {
7784  get_col_endpoint= get_partition_id_cols_list_for_endpoint;
7785  part_iter->get_next= get_next_partition_id_list;
7786  part_iter->part_info= part_info;
7787  DBUG_ASSERT(part_info->num_list_values);
7788  }
7789  else
7790  assert(0);
7791 
7792  if (flags & NO_MIN_RANGE)
7793  part_iter->part_nums.start= part_iter->part_nums.cur= 0;
7794  else
7795  {
7796  // Copy from min_value to record
7797  nparts= store_tuple_to_record(part_info->part_field_array,
7798  store_length_array,
7799  min_value,
7800  min_value + min_len);
7801  part_iter->part_nums.start= part_iter->part_nums.cur=
7802  get_col_endpoint(part_info, TRUE, !(flags & NEAR_MIN),
7803  nparts);
7804  }
7805  if (flags & NO_MAX_RANGE)
7806  {
7807  if (part_info->part_type == RANGE_PARTITION)
7808  part_iter->part_nums.end= part_info->num_parts;
7809  else /* LIST_PARTITION */
7810  {
7811  DBUG_ASSERT(part_info->part_type == LIST_PARTITION);
7812  part_iter->part_nums.end= part_info->num_list_values;
7813  }
7814  }
7815  else
7816  {
7817  // Copy from max_value to record
7818  nparts= store_tuple_to_record(part_info->part_field_array,
7819  store_length_array,
7820  max_value,
7821  max_value + max_len);
7822  part_iter->part_nums.end= get_col_endpoint(part_info, FALSE,
7823  !(flags & NEAR_MAX),
7824  nparts);
7825  }
7826  if (part_iter->part_nums.start == part_iter->part_nums.end)
7827  DBUG_RETURN(0);
7828  DBUG_RETURN(1);
7829 }
7830 
7831 
7866 int get_part_iter_for_interval_via_mapping(partition_info *part_info,
7867  bool is_subpart,
7868  uint32 *store_length_array, /* ignored */
7869  uchar *min_value, uchar *max_value,
7870  uint min_len, uint max_len, /* ignored */
7871  uint flags,
7872  PARTITION_ITERATOR *part_iter)
7873 {
7874  Field *field= part_info->part_field_array[0];
7875  uint32 UNINIT_VAR(max_endpoint_val);
7876  get_endpoint_func UNINIT_VAR(get_endpoint);
7877  bool can_match_multiple_values; /* is not '=' */
7878  uint field_len= field->pack_length_in_rec();
7879  MYSQL_TIME start_date;
7880  bool check_zero_dates= false;
7881  bool zero_in_start_date= true;
7882  DBUG_ENTER("get_part_iter_for_interval_via_mapping");
7883  DBUG_ASSERT(!is_subpart);
7884  (void) store_length_array;
7885  (void)min_len;
7886  (void)max_len;
7887  part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
7888 
7889  if (part_info->part_type == RANGE_PARTITION)
7890  {
7891  if (part_info->part_charset_field_array)
7892  get_endpoint= get_partition_id_range_for_endpoint_charset;
7893  else
7894  get_endpoint= get_partition_id_range_for_endpoint;
7895  max_endpoint_val= part_info->num_parts;
7896  part_iter->get_next= get_next_partition_id_range;
7897  }
7898  else if (part_info->part_type == LIST_PARTITION)
7899  {
7900 
7901  if (part_info->part_charset_field_array)
7902  get_endpoint= get_list_array_idx_for_endpoint_charset;
7903  else
7904  get_endpoint= get_list_array_idx_for_endpoint;
7905  max_endpoint_val= part_info->num_list_values;
7906  part_iter->get_next= get_next_partition_id_list;
7907  part_iter->part_info= part_info;
7908  if (max_endpoint_val == 0)
7909  {
7910  /*
7911  We handle this special case without optimisations since it is
7912  of little practical value but causes a great number of complex
7913  checks later in the code.
7914  */
7915  part_iter->part_nums.start= part_iter->part_nums.end= 0;
7916  part_iter->part_nums.cur= 0;
7917  part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
7918  DBUG_RETURN(-1);
7919  }
7920  }
7921  else
7922  MY_ASSERT_UNREACHABLE();
7923 
7924  can_match_multiple_values= (flags || !min_value || !max_value ||
7925  memcmp(min_value, max_value, field_len));
7926  if (can_match_multiple_values &&
7927  (part_info->part_type == RANGE_PARTITION ||
7928  part_info->has_null_value))
7929  {
7930  /* Range scan on RANGE or LIST partitioned table */
7931  enum_monotonicity_info monotonic;
7932  monotonic= part_info->part_expr->get_monotonicity_info();
7933  if (monotonic == MONOTONIC_INCREASING_NOT_NULL ||
7934  monotonic == MONOTONIC_STRICT_INCREASING_NOT_NULL)
7935  {
7936  /* col is NOT NULL, but F(col) can return NULL, add NULL partition */
7937  part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
7938  check_zero_dates= true;
7939  }
7940  }
7941 
7942  /*
7943  Find minimum: Do special handling if the interval has left bound in form
7944  " NULL <= X ":
7945  */
7946  if (field->real_maybe_null() && part_info->has_null_value &&
7947  !(flags & (NO_MIN_RANGE | NEAR_MIN)) && *min_value)
7948  {
7949  part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
7950  part_iter->part_nums.start= part_iter->part_nums.cur= 0;
7951  if (!(flags & NO_MAX_RANGE) && *max_value)
7952  {
7953  /* The right bound is X <= NULL, i.e. it is a "X IS NULL" interval */
7954  part_iter->part_nums.end= 0;
7955  DBUG_RETURN(1);
7956  }
7957  }
7958  else
7959  {
7960  if (flags & NO_MIN_RANGE)
7961  part_iter->part_nums.start= part_iter->part_nums.cur= 0;
7962  else
7963  {
7964  /*
7965  Store the interval edge in the record buffer, and call the
7966  function that maps the edge in table-field space to an edge
7967  in ordered-set-of-partitions (for RANGE partitioning) or
7968  index-in-ordered-array-of-list-constants (for LIST) space.
7969  */
7970  store_key_image_to_rec(field, min_value, field_len);
7971  bool include_endp= !test(flags & NEAR_MIN);
7972  part_iter->part_nums.start= get_endpoint(part_info, 1, include_endp);
7973  if (!can_match_multiple_values && part_info->part_expr->null_value)
7974  {
7975  /* col = x and F(x) = NULL -> only search NULL partition */
7976  part_iter->part_nums.cur= part_iter->part_nums.start= 0;
7977  part_iter->part_nums.end= 0;
7978  part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
7979  DBUG_RETURN(1);
7980  }
7981  part_iter->part_nums.cur= part_iter->part_nums.start;
7982  if (check_zero_dates && !part_info->part_expr->null_value)
7983  {
7984  if (!(flags & NO_MAX_RANGE) &&
7985  (field->type() == MYSQL_TYPE_DATE ||
7986  field->type() == MYSQL_TYPE_DATETIME))
7987  {
7988  /* Monotonic, but return NULL for dates with zeros in month/day. */
7989  zero_in_start_date= field->get_date(&start_date, 0);
7990  DBUG_PRINT("info", ("zero start %u %04d-%02d-%02d",
7991  zero_in_start_date, start_date.year,
7992  start_date.month, start_date.day));
7993  }
7994  }
7995  if (part_iter->part_nums.start == max_endpoint_val)
7996  DBUG_RETURN(0); /* No partitions */
7997  }
7998  }
7999 
8000  /* Find maximum, do the same as above but for right interval bound */
8001  if (flags & NO_MAX_RANGE)
8002  part_iter->part_nums.end= max_endpoint_val;
8003  else
8004  {
8005  store_key_image_to_rec(field, max_value, field_len);
8006  bool include_endp= !test(flags & NEAR_MAX);
8007  part_iter->part_nums.end= get_endpoint(part_info, 0, include_endp);
8008  if (check_zero_dates &&
8009  !zero_in_start_date &&
8010  !part_info->part_expr->null_value)
8011  {
8012  MYSQL_TIME end_date;
8013  bool zero_in_end_date= field->get_date(&end_date, 0);
8014  /*
8015  This is an optimization for TO_DAYS()/TO_SECONDS() to avoid scanning
8016  the NULL partition for ranges that cannot include a date with 0 as
8017  month/day.
8018  */
8019  DBUG_PRINT("info", ("zero end %u %04d-%02d-%02d",
8020  zero_in_end_date,
8021  end_date.year, end_date.month, end_date.day));
8022  DBUG_ASSERT(!memcmp(((Item_func*) part_info->part_expr)->func_name(),
8023  "to_days", 7) ||
8024  !memcmp(((Item_func*) part_info->part_expr)->func_name(),
8025  "to_seconds", 10));
8026  if (!zero_in_end_date &&
8027  start_date.month == end_date.month &&
8028  start_date.year == end_date.year)
8029  part_iter->ret_null_part= part_iter->ret_null_part_orig= false;
8030  }
8031  if (part_iter->part_nums.start >= part_iter->part_nums.end &&
8032  !part_iter->ret_null_part)
8033  DBUG_RETURN(0); /* No partitions */
8034  }
8035  DBUG_RETURN(1); /* Ok, iterator initialized */
8036 }
8037 
8038 
8039 /* See get_part_iter_for_interval_via_walking for definition of what this is */
8040 #define MAX_RANGE_TO_WALK 32
8041 
8042 
8043 /*
8044  Partitioning Interval Analysis: Initialize iterator to walk field interval
8045 
8046  SYNOPSIS
8047  get_part_iter_for_interval_via_walking()
8048  part_info Partition info
8049  is_subpart TRUE - act for subpartitioning
8050  FALSE - act for partitioning
8051  min_value minimum field value, in opt_range key format.
8052  max_value minimum field value, in opt_range key format.
8053  flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
8054  NO_MAX_RANGE.
8055  part_iter Iterator structure to be initialized
8056 
8057  DESCRIPTION
8058  Initialize partition set iterator to walk over interval in integer field
8059  space. That is, for "const1 <=? t.field <=? const2" interval, initialize
8060  the iterator to return a set of [sub]partitions obtained with the
8061  following procedure:
8062  get partition id for t.field = const1, return it
8063  get partition id for t.field = const1+1, return it
8064  ... t.field = const1+2, ...
8065  ... ... ...
8066  ... t.field = const2 ...
8067 
8068  IMPLEMENTATION
8069  See get_partitions_in_range_iter for general description of interval
8070  analysis. We support walking over the following intervals:
8071  "t.field IS NULL"
8072  "c1 <=? t.field <=? c2", where c1 and c2 are finite.
8073  Intervals with +inf/-inf, and [NULL, c1] interval can be processed but
8074  that is more tricky and I don't have time to do it right now.
8075 
8076  RETURN
8077  0 - No matching partitions, iterator not initialized
8078  1 - Some partitions would match, iterator intialized for traversing them
8079  -1 - All partitions would match, iterator not initialized
8080 */
8081 
8082 int get_part_iter_for_interval_via_walking(partition_info *part_info,
8083  bool is_subpart,
8084  uint32 *store_length_array, /* ignored */
8085  uchar *min_value, uchar *max_value,
8086  uint min_len, uint max_len, /* ignored */
8087  uint flags,
8088  PARTITION_ITERATOR *part_iter)
8089 {
8090  Field *field;
8091  uint total_parts;
8092  partition_iter_func get_next_func;
8093  DBUG_ENTER("get_part_iter_for_interval_via_walking");
8094  (void)store_length_array;
8095  (void)min_len;
8096  (void)max_len;
8097 
8098  part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
8099  if (is_subpart)
8100  {
8101  field= part_info->subpart_field_array[0];
8102  total_parts= part_info->num_subparts;
8103  get_next_func= get_next_subpartition_via_walking;
8104  }
8105  else
8106  {
8107  field= part_info->part_field_array[0];
8108  total_parts= part_info->num_parts;
8109  get_next_func= get_next_partition_via_walking;
8110  }
8111 
8112  /* Handle the "t.field IS NULL" interval, it is a special case */
8113  if (field->real_maybe_null() && !(flags & (NO_MIN_RANGE | NO_MAX_RANGE)) &&
8114  *min_value && *max_value)
8115  {
8116  /*
8117  We don't have a part_iter->get_next() function that would find which
8118  partition "t.field IS NULL" belongs to, so find partition that contains
8119  NULL right here, and return an iterator over singleton set.
8120  */
8121  uint32 part_id;
8122  field->set_null();
8123  if (is_subpart)
8124  {
8125  if (!part_info->get_subpartition_id(part_info, &part_id))
8126  {
8127  init_single_partition_iterator(part_id, part_iter);
8128  DBUG_RETURN(1); /* Ok, iterator initialized */
8129  }
8130  }
8131  else
8132  {
8133  longlong dummy;
8134  int res= part_info->is_sub_partitioned() ?
8135  part_info->get_part_partition_id(part_info, &part_id,
8136  &dummy):
8137  part_info->get_partition_id(part_info, &part_id, &dummy);
8138  if (!res)
8139  {
8140  init_single_partition_iterator(part_id, part_iter);
8141  DBUG_RETURN(1); /* Ok, iterator initialized */
8142  }
8143  }
8144  DBUG_RETURN(0); /* No partitions match */
8145  }
8146 
8147  if ((field->real_maybe_null() &&
8148  ((!(flags & NO_MIN_RANGE) && *min_value) || // NULL <? X
8149  (!(flags & NO_MAX_RANGE) && *max_value))) || // X <? NULL
8150  (flags & (NO_MIN_RANGE | NO_MAX_RANGE))) // -inf at any bound
8151  {
8152  DBUG_RETURN(-1); /* Can't handle this interval, have to use all partitions */
8153  }
8154 
8155  /* Get integers for left and right interval bound */
8156  longlong a, b;
8157  uint len= field->pack_length_in_rec();
8158  store_key_image_to_rec(field, min_value, len);
8159  a= field->val_int();
8160 
8161  store_key_image_to_rec(field, max_value, len);
8162  b= field->val_int();
8163 
8164  /*
8165  Handle a special case where the distance between interval bounds is
8166  exactly 4G-1. This interval is too big for range walking, and if it is an
8167  (x,y]-type interval then the following "b +=..." code will convert it to
8168  an empty interval by "wrapping around" a + 4G-1 + 1 = a.
8169  */
8170  if ((ulonglong)b - (ulonglong)a == ~0ULL)
8171  DBUG_RETURN(-1);
8172 
8173  a += test(flags & NEAR_MIN);
8174  b += test(!(flags & NEAR_MAX));
8175  ulonglong n_values= b - a;
8176 
8177  /*
8178  Will it pay off to enumerate all values in the [a..b] range and evaluate
8179  the partitioning function for every value? It depends on
8180  1. whether we'll be able to infer that some partitions are not used
8181  2. if time savings from not scanning these partitions will be greater
8182  than time spent in enumeration.
8183  We will assume that the cost of accessing one extra partition is greater
8184  than the cost of evaluating the partitioning function O(#partitions).
8185  This means we should jump at any chance to eliminate a partition, which
8186  gives us this logic:
8187 
8188  Do the enumeration if
8189  - the number of values to enumerate is comparable to the number of
8190  partitions, or
8191  - there are not many values to enumerate.
8192  */
8193  if ((n_values > 2*total_parts) && n_values > MAX_RANGE_TO_WALK)
8194  DBUG_RETURN(-1);
8195 
8196  part_iter->field_vals.start= part_iter->field_vals.cur= a;
8197  part_iter->field_vals.end= b;
8198  part_iter->part_info= part_info;
8199  part_iter->get_next= get_next_func;
8200  DBUG_RETURN(1);
8201 }
8202 
8203 
8204 /*
8205  PARTITION_ITERATOR::get_next implementation: enumerate partitions in range
8206 
8207  SYNOPSIS
8208  get_next_partition_id_range()
8209  part_iter Partition set iterator structure
8210 
8211  DESCRIPTION
8212  This is implementation of PARTITION_ITERATOR::get_next() that returns
8213  [sub]partition ids in [min_partition_id, max_partition_id] range.
8214  The function conforms to partition_iter_func type.
8215 
8216  RETURN
8217  partition id
8218  NOT_A_PARTITION_ID if there are no more partitions
8219 */
8220 
8221 uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
8222 {
8223  if (part_iter->part_nums.cur >= part_iter->part_nums.end)
8224  {
8225  if (part_iter->ret_null_part)
8226  {
8227  part_iter->ret_null_part= FALSE;
8228  return 0; /* NULL always in first range partition */
8229  }
8230  part_iter->part_nums.cur= part_iter->part_nums.start;
8231  part_iter->ret_null_part= part_iter->ret_null_part_orig;
8232  return NOT_A_PARTITION_ID;
8233  }
8234  else
8235  return part_iter->part_nums.cur++;
8236 }
8237 
8238 
8239 /*
8240  PARTITION_ITERATOR::get_next implementation for LIST partitioning
8241 
8242  SYNOPSIS
8243  get_next_partition_id_list()
8244  part_iter Partition set iterator structure
8245 
8246  DESCRIPTION
8247  This implementation of PARTITION_ITERATOR::get_next() is special for
8248  LIST partitioning: it enumerates partition ids in
8249  part_info->list_array[i] (list_col_array[i*cols] for COLUMNS LIST
8250  partitioning) where i runs over [min_idx, max_idx] interval.
8251  The function conforms to partition_iter_func type.
8252 
8253  RETURN
8254  partition id
8255  NOT_A_PARTITION_ID if there are no more partitions
8256 */
8257 
8258 uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter)
8259 {
8260  if (part_iter->part_nums.cur >= part_iter->part_nums.end)
8261  {
8262  if (part_iter->ret_null_part)
8263  {
8264  part_iter->ret_null_part= FALSE;
8265  return part_iter->part_info->has_null_part_id;
8266  }
8267  part_iter->part_nums.cur= part_iter->part_nums.start;
8268  part_iter->ret_null_part= part_iter->ret_null_part_orig;
8269  return NOT_A_PARTITION_ID;
8270  }
8271  else
8272  {
8273  partition_info *part_info= part_iter->part_info;
8274  uint32 num_part= part_iter->part_nums.cur++;
8275  if (part_info->column_list)
8276  {
8277  uint num_columns= part_info->part_field_list.elements;
8278  return part_info->list_col_array[num_part*num_columns].partition_id;
8279  }
8280  return part_info->list_array[num_part].partition_id;
8281  }
8282 }
8283 
8284 
8285 /*
8286  PARTITION_ITERATOR::get_next implementation: walk over field-space interval
8287 
8288  SYNOPSIS
8289  get_next_partition_via_walking()
8290  part_iter Partitioning iterator
8291 
8292  DESCRIPTION
8293  This implementation of PARTITION_ITERATOR::get_next() returns ids of
8294  partitions that contain records with partitioning field value within
8295  [start_val, end_val] interval.
8296  The function conforms to partition_iter_func type.
8297 
8298  RETURN
8299  partition id
8300  NOT_A_PARTITION_ID if there are no more partitioning.
8301 */
8302 
8303 static uint32 get_next_partition_via_walking(PARTITION_ITERATOR *part_iter)
8304 {
8305  uint32 part_id;
8306  Field *field= part_iter->part_info->part_field_array[0];
8307  while (part_iter->field_vals.cur != part_iter->field_vals.end)
8308  {
8309  longlong dummy;
8310  field->store(part_iter->field_vals.cur++, field->flags & UNSIGNED_FLAG);
8311  if ((part_iter->part_info->is_sub_partitioned() &&
8312  !part_iter->part_info->get_part_partition_id(part_iter->part_info,
8313  &part_id, &dummy)) ||
8314  !part_iter->part_info->get_partition_id(part_iter->part_info,
8315  &part_id, &dummy))
8316  return part_id;
8317  }
8318  part_iter->field_vals.cur= part_iter->field_vals.start;
8319  return NOT_A_PARTITION_ID;
8320 }
8321 
8322 
8323 /* Same as get_next_partition_via_walking, but for subpartitions */
8324 
8325 static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter)
8326 {
8327  Field *field= part_iter->part_info->subpart_field_array[0];
8328  uint32 res;
8329  if (part_iter->field_vals.cur == part_iter->field_vals.end)
8330  {
8331  part_iter->field_vals.cur= part_iter->field_vals.start;
8332  return NOT_A_PARTITION_ID;
8333  }
8334  field->store(part_iter->field_vals.cur++, field->flags & UNSIGNED_FLAG);
8335  if (part_iter->part_info->get_subpartition_id(part_iter->part_info,
8336  &res))
8337  return NOT_A_PARTITION_ID;
8338  return res;
8339 }
8340 
8341 
8342 /*
8343  Create partition names
8344 
8345  SYNOPSIS
8346  create_partition_name()
8347  out:out Created partition name string
8348  in1 First part
8349  in2 Second part
8350  name_variant Normal, temporary or renamed partition name
8351 
8352  RETURN VALUE
8353  NONE
8354 
8355  DESCRIPTION
8356  This method is used to calculate the partition name, service routine to
8357  the del_ren_cre_table method.
8358 */
8359 
8360 void create_partition_name(char *out, const char *in1,
8361  const char *in2, uint name_variant,
8362  bool translate)
8363 {
8364  char transl_part_name[FN_REFLEN];
8365  const char *transl_part;
8366 
8367  if (translate)
8368  {
8369  tablename_to_filename(in2, transl_part_name, FN_REFLEN);
8370  transl_part= transl_part_name;
8371  }
8372  else
8373  transl_part= in2;
8374  if (name_variant == NORMAL_PART_NAME)
8375  strxmov(out, in1, "#P#", transl_part, NullS);
8376  else if (name_variant == TEMP_PART_NAME)
8377  strxmov(out, in1, "#P#", transl_part, "#TMP#", NullS);
8378  else if (name_variant == RENAMED_PART_NAME)
8379  strxmov(out, in1, "#P#", transl_part, "#REN#", NullS);
8380 }
8381 
8382 
8383 /*
8384  Create subpartition name
8385 
8386  SYNOPSIS
8387  create_subpartition_name()
8388  out:out Created partition name string
8389  in1 First part
8390  in2 Second part
8391  in3 Third part
8392  name_variant Normal, temporary or renamed partition name
8393 
8394  RETURN VALUE
8395  NONE
8396 
8397  DESCRIPTION
8398  This method is used to calculate the subpartition name, service routine to
8399  the del_ren_cre_table method.
8400 */
8401 
8402 void create_subpartition_name(char *out, const char *in1,
8403  const char *in2, const char *in3,
8404  uint name_variant)
8405 {
8406  char transl_part_name[FN_REFLEN], transl_subpart_name[FN_REFLEN];
8407 
8408  tablename_to_filename(in2, transl_part_name, FN_REFLEN);
8409  tablename_to_filename(in3, transl_subpart_name, FN_REFLEN);
8410  if (name_variant == NORMAL_PART_NAME)
8411  strxmov(out, in1, "#P#", transl_part_name,
8412  "#SP#", transl_subpart_name, NullS);
8413  else if (name_variant == TEMP_PART_NAME)
8414  strxmov(out, in1, "#P#", transl_part_name,
8415  "#SP#", transl_subpart_name, "#TMP#", NullS);
8416  else if (name_variant == RENAMED_PART_NAME)
8417  strxmov(out, in1, "#P#", transl_part_name,
8418  "#SP#", transl_subpart_name, "#REN#", NullS);
8419 }
8420 
8421 uint get_partition_field_store_length(Field *field)
8422 {
8423  uint store_length;
8424 
8425  store_length= field->key_length();
8426  if (field->real_maybe_null())
8427  store_length+= HA_KEY_NULL_LENGTH;
8428  if (field->real_type() == MYSQL_TYPE_VARCHAR)
8429  store_length+= HA_KEY_BLOB_LENGTH;
8430  return store_length;
8431 }
8432 #endif
8433