1 #ifndef PARTITION_INFO_INCLUDED
2 #define PARTITION_INFO_INCLUDED
3 
4 /* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License, version 2.0,
8    as published by the Free Software Foundation.
9 
10    This program is also distributed with certain software (including
11    but not limited to OpenSSL) that is licensed under separate terms,
12    as designated in a particular file or component or in included license
13    documentation.  The authors of MySQL hereby grant you an additional
14    permission to link the program and your derivative works with the
15    separately licensed software that they have included with MySQL.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License, version 2.0, for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
25 
26 #include "partition_element.h"
27 #include "sql_class.h"                        // enum_duplicates
28 
29 class partition_info;
30 class COPY_INFO;
31 struct TABLE_LIST;
32 
33 /* Some function typedefs */
34 typedef int (*get_part_id_func)(partition_info *part_info,
35                                  uint32 *part_id,
36                                  longlong *func_value);
37 typedef int (*get_subpart_id_func)(partition_info *part_info,
38                                    uint32 *part_id);
39 
40 struct st_ddl_log_memory_entry;
41 
42 class partition_info : public Sql_alloc
43 {
44 public:
45   /*
46    * Here comes a set of definitions needed for partitioned table handlers.
47    */
48   List<partition_element> partitions;
49   List<partition_element> temp_partitions;
50 
51   List<char> part_field_list;
52   List<char> subpart_field_list;
53 
54   /*
55     If there is no subpartitioning, use only this func to get partition ids.
56     If there is subpartitioning, use the this func to get partition id when
57     you have both partition and subpartition fields.
58   */
59   get_part_id_func get_partition_id;
60 
61   /* Get partition id when we don't have subpartition fields */
62   get_part_id_func get_part_partition_id;
63 
64   /*
65     Get subpartition id when we have don't have partition fields by we do
66     have subpartition ids.
67     Mikael said that for given constant tuple
68     {subpart_field1, ..., subpart_fieldN} the subpartition id will be the
69     same in all subpartitions
70   */
71   get_subpart_id_func get_subpartition_id;
72 
73   /*
74     When we have various string fields we might need some preparation
75     before and clean-up after calling the get_part_id_func's. We need
76     one such method for get_part_partition_id and one for
77     get_subpartition_id.
78   */
79   get_part_id_func get_part_partition_id_charset;
80   get_subpart_id_func get_subpartition_id_charset;
81 
82   /* NULL-terminated array of fields used in partitioned expression */
83   Field **part_field_array;
84   Field **subpart_field_array;
85   Field **part_charset_field_array;
86   Field **subpart_charset_field_array;
87   /*
88     Array of all fields used in partition and subpartition expression,
89     without duplicates, NULL-terminated.
90   */
91   Field **full_part_field_array;
92   /*
93     Set of all fields used in partition and subpartition expression.
94     Required for testing of partition fields in write_set when
95     updating. We need to set all bits in read_set because the row may
96     need to be inserted in a different [sub]partition.
97   */
98   MY_BITMAP full_part_field_set;
99 
100   /*
101     When we have a field that requires transformation before calling the
102     partition functions we must allocate field buffers for the field of
103     the fields in the partition function.
104   */
105   uchar **part_field_buffers;
106   uchar **subpart_field_buffers;
107   uchar **restore_part_field_ptrs;
108   uchar **restore_subpart_field_ptrs;
109 
110   Item *part_expr;
111   Item *subpart_expr;
112 
113   Item *item_free_list;
114 
115   struct st_ddl_log_memory_entry *first_log_entry;
116   struct st_ddl_log_memory_entry *exec_log_entry;
117   struct st_ddl_log_memory_entry *frm_log_entry;
118 
119   /*
120     Bitmaps of partitions used by the current query.
121     * read_partitions  - partitions to be used for reading.
122     * lock_partitions  - partitions that must be locked (read or write).
123     Usually read_partitions is the same set as lock_partitions, but
124     in case of UPDATE the WHERE clause can limit the read_partitions set,
125     but not neccesarily the lock_partitions set.
126     Usage pattern:
127     * Initialized in ha_partition::open().
128     * read+lock_partitions is set  according to explicit PARTITION,
129       WL#5217, in open_and_lock_tables().
130     * Bits in read_partitions can be cleared in prune_partitions()
131       in the optimizing step.
132       (WL#4443 is about allowing prune_partitions() to affect lock_partitions
133       and be done before locking too).
134     * When the partition enabled handler get an external_lock call it locks
135       all partitions in lock_partitions (and remembers which partitions it
136       locked, so that it can unlock them later). In case of LOCK TABLES it will
137       lock all partitions, and keep them locked while lock_partitions can
138       change for each statement under LOCK TABLES.
139     * Freed at the same time item_free_list is freed.
140   */
141   MY_BITMAP read_partitions;
142   MY_BITMAP lock_partitions;
143   bool bitmaps_are_initialized;
144 
145   union {
146     longlong *range_int_array;
147     LIST_PART_ENTRY *list_array;
148     part_column_list_val *range_col_array;
149     part_column_list_val *list_col_array;
150   };
151 
152   /********************************************
153    * INTERVAL ANALYSIS
154    ********************************************/
155   /*
156     Partitioning interval analysis function for partitioning, or NULL if
157     interval analysis is not supported for this kind of partitioning.
158   */
159   get_partitions_in_range_iter get_part_iter_for_interval;
160   /*
161     Partitioning interval analysis function for subpartitioning, or NULL if
162     interval analysis is not supported for this kind of partitioning.
163   */
164   get_partitions_in_range_iter get_subpart_iter_for_interval;
165 
166   /********************************************
167    * INTERVAL ANALYSIS ENDS
168    ********************************************/
169 
170   longlong err_value;
171   char* part_info_string;
172 
173   char *part_func_string;
174   char *subpart_func_string;
175 
176   partition_element *curr_part_elem;     // part or sub part
177   partition_element *current_partition;  // partition
178   part_elem_value *curr_list_val;
179   uint curr_list_object;
180   uint num_columns;
181 
182   TABLE *table;
183   /*
184     These key_map's are used for Partitioning to enable quick decisions
185     on whether we can derive more information about which partition to
186     scan just by looking at what index is used.
187   */
188   key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF;
189   key_map some_fields_in_PF;
190 
191   handlerton *default_engine_type;
192   partition_type part_type;
193   partition_type subpart_type;
194 
195   uint part_info_len;
196   uint part_func_len;
197   uint subpart_func_len;
198 
199   uint num_parts;
200   uint num_subparts;
201   uint count_curr_subparts;                  // used during parsing
202 
203   uint num_list_values;
204 
205   uint num_part_fields;
206   uint num_subpart_fields;
207   uint num_full_part_fields;
208 
209   uint has_null_part_id;
210   /*
211     This variable is used to calculate the partition id when using
212     LINEAR KEY/HASH. This functionality is kept in the MySQL Server
213     but mainly of use to handlers supporting partitioning.
214   */
215   uint16 linear_hash_mask;
216   /*
217     PARTITION BY KEY ALGORITHM=N
218     Which algorithm to use for hashing the fields.
219     N = 1 - Use 5.1 hashing (numeric fields are hashed as binary)
220     N = 2 - Use 5.5 hashing (numeric fields are hashed like latin1 bytes)
221   */
222   enum enum_key_algorithm
223     {
224       KEY_ALGORITHM_NONE= 0,
225       KEY_ALGORITHM_51= 1,
226       KEY_ALGORITHM_55= 2
227     };
228   enum_key_algorithm key_algorithm;
229 
230   /* Only the number of partitions defined (uses default names and options). */
231   bool use_default_partitions;
232   bool use_default_num_partitions;
233   /* Only the number of subpartitions defined (uses default names etc.). */
234   bool use_default_subpartitions;
235   bool use_default_num_subpartitions;
236   bool default_partitions_setup;
237   bool defined_max_value;
238   bool list_of_part_fields;                  // KEY or COLUMNS PARTITIONING
239   bool list_of_subpart_fields;               // KEY SUBPARTITIONING
240   bool linear_hash_ind;                      // LINEAR HASH/KEY
241   bool fixed;
242   bool is_auto_partitioned;
243   bool has_null_value;
244   bool column_list;                          // COLUMNS PARTITIONING, 5.5+
245   /**
246     True if pruning has been completed and can not be pruned any further,
247     even if there are subqueries or stored programs in the condition.
248 
249     Some times it is needed to run prune_partitions() a second time to prune
250     read partitions after tables are locked, when subquery and
251     stored functions might have been evaluated.
252   */
253   bool is_pruning_completed;
254 
partition_info()255   partition_info()
256   : get_partition_id(NULL), get_part_partition_id(NULL),
257     get_subpartition_id(NULL),
258     part_field_array(NULL), subpart_field_array(NULL),
259     part_charset_field_array(NULL),
260     subpart_charset_field_array(NULL),
261     full_part_field_array(NULL),
262     part_field_buffers(NULL), subpart_field_buffers(NULL),
263     restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL),
264     part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
265     first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL),
266     bitmaps_are_initialized(FALSE),
267     list_array(NULL), err_value(0),
268     part_info_string(NULL),
269     part_func_string(NULL), subpart_func_string(NULL),
270     curr_part_elem(NULL), current_partition(NULL),
271     curr_list_object(0), num_columns(0), table(NULL),
272     default_engine_type(NULL),
273     part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
274     part_info_len(0),
275     part_func_len(0), subpart_func_len(0),
276     num_parts(0), num_subparts(0),
277     count_curr_subparts(0),
278     num_list_values(0), num_part_fields(0), num_subpart_fields(0),
279     num_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
280     key_algorithm(KEY_ALGORITHM_NONE),
281     use_default_partitions(TRUE), use_default_num_partitions(TRUE),
282     use_default_subpartitions(TRUE), use_default_num_subpartitions(TRUE),
283     default_partitions_setup(FALSE), defined_max_value(FALSE),
284     list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
285     linear_hash_ind(FALSE), fixed(FALSE),
286     is_auto_partitioned(FALSE),
287     has_null_value(FALSE), column_list(FALSE), is_pruning_completed(false)
288   {
289     partitions.empty();
290     temp_partitions.empty();
291     part_field_list.empty();
292     subpart_field_list.empty();
293   }
~partition_info()294   ~partition_info() {}
295 
296   partition_info *get_clone(bool reset = false);
297   partition_info *get_full_clone();
298   bool set_named_partition_bitmap(const char *part_name, uint length);
299   bool set_partition_bitmaps(TABLE_LIST *table_list);
300   /* Answers the question if subpartitioning is used for a certain table */
is_sub_partitioned()301   bool is_sub_partitioned()
302   {
303     return (subpart_type == NOT_A_PARTITION ?  FALSE : TRUE);
304   }
305 
306   /* Returns the total number of partitions on the leaf level */
get_tot_partitions()307   uint get_tot_partitions()
308   {
309     return num_parts * (is_sub_partitioned() ? num_subparts : 1);
310   }
311 
312   bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info,
313                                         uint start_no);
314   char *find_duplicate_field();
315   char *find_duplicate_name();
316   bool check_engine_mix(handlerton *engine_type, bool default_engine);
317   bool check_range_constants(THD *thd);
318   bool check_list_constants(THD *thd);
319   bool check_partition_info(THD *thd, handlerton **eng_type,
320                             handler *file, HA_CREATE_INFO *info,
321                             bool check_partition_function);
322   void print_no_partition_found(TABLE *table);
323   void print_debug(const char *str, uint*);
324   Item* get_column_item(Item *item, Field *field);
325   bool fix_partition_values(THD *thd,
326                             part_elem_value *val,
327                             partition_element *part_elem,
328                             uint part_id);
329   bool fix_column_value_functions(THD *thd,
330                                   part_elem_value *val,
331                                   uint part_id);
332   bool fix_parser_data(THD *thd);
333   bool add_max_value();
334   void init_col_val(part_column_list_val *col_val, Item *item);
335   bool reorganize_into_single_field_col_val();
336   part_column_list_val *add_column_value();
337   bool set_part_expr(char *start_token, Item *item_ptr,
338                      char *end_token, bool is_subpart);
339   static int compare_column_values(const void *a, const void *b);
340   bool set_up_charset_field_preps();
341   bool check_partition_field_length();
342   bool init_column_part();
343   bool add_column_list_value(THD *thd, Item *item);
344   void set_show_version_string(String *packet);
345   partition_element *get_part_elem(const char *partition_name,
346                                    char *file_name,
347                                    uint32 *part_id);
348   void report_part_expr_error(bool use_subpart_expr);
349   bool set_used_partition(List<Item> &fields,
350                           List<Item> &values,
351                           COPY_INFO &info,
352                           bool copy_default_values,
353                           MY_BITMAP *used_partitions);
354   /**
355     PRUNE_NO - Unable to prune.
356     PRUNE_DEFAULTS - Partitioning field is only set to
357                      DEFAULT values, only need to check
358                      pruning for one row where the DEFAULTS
359                      values are set.
360     PRUNE_YES - Pruning is possible, calculate the used partition set
361                 by evaluate the partition_id on row by row basis.
362   */
363   enum enum_can_prune {PRUNE_NO=0, PRUNE_DEFAULTS, PRUNE_YES};
364   bool can_prune_insert(THD *thd,
365                         enum_duplicates duplic,
366                         COPY_INFO &update,
367                         List<Item> &update_fields,
368                         List<Item> &fields,
369                         bool empty_values,
370                         enum_can_prune *can_prune_partitions,
371                         bool *prune_needs_default_values,
372                         MY_BITMAP *used_partitions);
373   bool has_same_partitioning(partition_info *new_part_info);
374 private:
375   static int list_part_cmp(const void* a, const void* b);
376   bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
377                                  uint start_no);
378   bool set_up_default_subpartitions(handler *file, HA_CREATE_INFO *info);
379   char *create_default_partition_names(uint part_no, uint num_parts,
380                                        uint start_no);
381   char *create_default_subpartition_name(uint subpart_no,
382                                          const char *part_name);
383   bool prune_partition_bitmaps(TABLE_LIST *table_list);
384   bool add_named_partition(const char *part_name, uint length);
385   bool is_field_in_part_expr(List<Item> &fields);
386   bool is_full_part_expr_in_fields(List<Item> &fields);
387 };
388 
389 uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
390 bool check_partition_dirs(partition_info *part_info);
391 
392 /* Initialize the iterator to return a single partition with given part_id */
393 
init_single_partition_iterator(uint32 part_id,PARTITION_ITERATOR * part_iter)394 static inline void init_single_partition_iterator(uint32 part_id,
395                                            PARTITION_ITERATOR *part_iter)
396 {
397   part_iter->part_nums.start= part_iter->part_nums.cur= part_id;
398   part_iter->part_nums.end= part_id+1;
399   part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
400   part_iter->get_next= get_next_partition_id_range;
401 }
402 
403 /* Initialize the iterator to enumerate all partitions */
404 static inline
init_all_partitions_iterator(partition_info * part_info,PARTITION_ITERATOR * part_iter)405 void init_all_partitions_iterator(partition_info *part_info,
406                                   PARTITION_ITERATOR *part_iter)
407 {
408   part_iter->part_nums.start= part_iter->part_nums.cur= 0;
409   part_iter->part_nums.end= part_info->num_parts;
410   part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
411   part_iter->get_next= get_next_partition_id_range;
412 }
413 
414 /**
415   Predicate which returns true if any partition or subpartition uses
416   an external data directory or external index directory.
417 
418   @param pi partitioning information
419   @retval true if any partition or subpartition has an external
420   data directory or external index directory.
421   @retval false otherwise
422  */
423 bool has_external_data_or_index_dir(partition_info &pi);
424 
425 #endif /* PARTITION_INFO_INCLUDED */
426