1 #ifndef PARTITION_INFO_INCLUDED
2 #define PARTITION_INFO_INCLUDED
3 
4 /* Copyright (c) 2006, 2010, 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 as published by
8    the Free Software Foundation; version 2 of the License.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1335  USA */
18 
19 #ifdef USE_PRAGMA_INTERFACE
20 #pragma interface			/* gcc class implementation */
21 #endif
22 
23 #include "sql_class.h"
24 #include "partition_element.h"
25 #include "sql_partition.h"
26 
27 class partition_info;
28 struct TABLE_LIST;
29 /* Some function typedefs */
30 typedef int (*get_part_id_func)(partition_info *part_info, uint32 *part_id,
31                                  longlong *func_value);
32 typedef int (*get_subpart_id_func)(partition_info *part_info, uint32 *part_id);
33 typedef bool (*check_constants_func)(THD *thd, partition_info *part_info);
34 
35 struct st_ddl_log_memory_entry;
36 
37 struct Vers_part_info : public Sql_alloc
38 {
Vers_part_infoVers_part_info39   Vers_part_info() :
40     limit(0),
41     now_part(NULL),
42     hist_part(NULL)
43   {
44     interval.type= INTERVAL_LAST;
45   }
Vers_part_infoVers_part_info46   Vers_part_info(Vers_part_info &src) :
47     interval(src.interval),
48     limit(src.limit),
49     now_part(NULL),
50     hist_part(NULL)
51   {
52   }
initializedVers_part_info53   bool initialized()
54   {
55     if (now_part)
56     {
57       DBUG_ASSERT(now_part->id != UINT_MAX32);
58       DBUG_ASSERT(now_part->type == partition_element::CURRENT);
59       if (hist_part)
60       {
61         DBUG_ASSERT(hist_part->id != UINT_MAX32);
62         DBUG_ASSERT(hist_part->type == partition_element::HISTORY);
63       }
64       return true;
65     }
66     return false;
67   }
68   struct {
69     my_time_t start;
70     INTERVAL step;
71     enum interval_type type;
is_setVers_part_info::__anon1f8fdb3e010872     bool is_set() { return type < INTERVAL_LAST; }
73   } interval;
74   ulonglong limit;
75   partition_element *now_part;
76   partition_element *hist_part;
77 };
78 
79 class partition_info : public Sql_alloc
80 {
81 public:
82   /*
83    * Here comes a set of definitions needed for partitioned table handlers.
84    */
85   List<partition_element> partitions;
86   List<partition_element> temp_partitions;
87 
88   List<const char> part_field_list;
89   List<const char> subpart_field_list;
90 
91   /*
92     If there is no subpartitioning, use only this func to get partition ids.
93     If there is subpartitioning, use the this func to get partition id when
94     you have both partition and subpartition fields.
95   */
96   get_part_id_func get_partition_id;
97 
98   /* Get partition id when we don't have subpartition fields */
99   get_part_id_func get_part_partition_id;
100 
101   /*
102     Get subpartition id when we have don't have partition fields by we do
103     have subpartition ids.
104     Mikael said that for given constant tuple
105     {subpart_field1, ..., subpart_fieldN} the subpartition id will be the
106     same in all subpartitions
107   */
108   get_subpart_id_func get_subpartition_id;
109 
110   /*
111     When we have various string fields we might need some preparation
112     before and clean-up after calling the get_part_id_func's. We need
113     one such method for get_part_partition_id and one for
114     get_subpartition_id.
115   */
116   get_part_id_func get_part_partition_id_charset;
117   get_subpart_id_func get_subpartition_id_charset;
118 
119   check_constants_func check_constants;
120 
121   /* NULL-terminated array of fields used in partitioned expression */
122   Field **part_field_array;
123   Field **subpart_field_array;
124   Field **part_charset_field_array;
125   Field **subpart_charset_field_array;
126   /*
127     Array of all fields used in partition and subpartition expression,
128     without duplicates, NULL-terminated.
129   */
130   Field **full_part_field_array;
131   /*
132     Set of all fields used in partition and subpartition expression.
133     Required for testing of partition fields in write_set when
134     updating. We need to set all bits in read_set because the row may
135     need to be inserted in a different [sub]partition.
136   */
137   MY_BITMAP full_part_field_set;
138 
139   /*
140     When we have a field that requires transformation before calling the
141     partition functions we must allocate field buffers for the field of
142     the fields in the partition function.
143   */
144   uchar **part_field_buffers;
145   uchar **subpart_field_buffers;
146   uchar **restore_part_field_ptrs;
147   uchar **restore_subpart_field_ptrs;
148 
149   Item *part_expr;
150   Item *subpart_expr;
151 
152   Item *item_free_list;
153 
154   struct st_ddl_log_memory_entry *first_log_entry;
155   struct st_ddl_log_memory_entry *exec_log_entry;
156   struct st_ddl_log_memory_entry *frm_log_entry;
157 
158   /*
159     Bitmaps of partitions used by the current query.
160     * read_partitions  - partitions to be used for reading.
161     * lock_partitions  - partitions that must be locked (read or write).
162     Usually read_partitions is the same set as lock_partitions, but
163     in case of UPDATE the WHERE clause can limit the read_partitions set,
164     but not neccesarily the lock_partitions set.
165     Usage pattern:
166     * Initialized in ha_partition::open().
167     * read+lock_partitions is set  according to explicit PARTITION,
168       WL#5217, in open_and_lock_tables().
169     * Bits in read_partitions can be cleared in prune_partitions()
170       in the optimizing step.
171       (WL#4443 is about allowing prune_partitions() to affect lock_partitions
172       and be done before locking too).
173     * When the partition enabled handler get an external_lock call it locks
174       all partitions in lock_partitions (and remembers which partitions it
175       locked, so that it can unlock them later). In case of LOCK TABLES it will
176       lock all partitions, and keep them locked while lock_partitions can
177       change for each statement under LOCK TABLES.
178     * Freed at the same time item_free_list is freed.
179   */
180   MY_BITMAP read_partitions;
181   MY_BITMAP lock_partitions;
182   bool bitmaps_are_initialized;
183 
184   union {
185     longlong *range_int_array;
186     LIST_PART_ENTRY *list_array;
187     part_column_list_val *range_col_array;
188     part_column_list_val *list_col_array;
189   };
190 
191   Vers_part_info *vers_info;
192 
193   /********************************************
194    * INTERVAL ANALYSIS
195    ********************************************/
196   /*
197     Partitioning interval analysis function for partitioning, or NULL if
198     interval analysis is not supported for this kind of partitioning.
199   */
200   get_partitions_in_range_iter get_part_iter_for_interval;
201   /*
202     Partitioning interval analysis function for subpartitioning, or NULL if
203     interval analysis is not supported for this kind of partitioning.
204   */
205   get_partitions_in_range_iter get_subpart_iter_for_interval;
206 
207   /********************************************
208    * INTERVAL ANALYSIS ENDS
209    ********************************************/
210 
211   longlong err_value;
212   char* part_info_string;
213 
214   partition_element *curr_part_elem;     // part or sub part
215   partition_element *current_partition;  // partition
216   part_elem_value *curr_list_val;
217   uint curr_list_object;
218   uint num_columns;
219 
220   TABLE *table;
221   /*
222     These key_map's are used for Partitioning to enable quick decisions
223     on whether we can derive more information about which partition to
224     scan just by looking at what index is used.
225   */
226   key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF;
227   key_map some_fields_in_PF;
228 
229   handlerton *default_engine_type;
230   partition_type part_type;
231   partition_type subpart_type;
232 
233   uint part_info_len;
234 
235   uint num_parts;
236   uint num_subparts;
237   uint count_curr_subparts;                  // used during parsing
238 
239   uint num_list_values;
240 
241   uint num_part_fields;
242   uint num_subpart_fields;
243   uint num_full_part_fields;
244 
245   uint has_null_part_id;
246   uint32 default_partition_id;
247   /*
248     This variable is used to calculate the partition id when using
249     LINEAR KEY/HASH. This functionality is kept in the MySQL Server
250     but mainly of use to handlers supporting partitioning.
251   */
252   uint16 linear_hash_mask;
253   /*
254     PARTITION BY KEY ALGORITHM=N
255     Which algorithm to use for hashing the fields.
256     N = 1 - Use 5.1 hashing (numeric fields are hashed as binary)
257     N = 2 - Use 5.5 hashing (numeric fields are hashed like latin1 bytes)
258   */
259   enum enum_key_algorithm
260     {
261       KEY_ALGORITHM_NONE= 0,
262       KEY_ALGORITHM_51= 1,
263       KEY_ALGORITHM_55= 2
264     };
265   enum_key_algorithm key_algorithm;
266 
267   /* Only the number of partitions defined (uses default names and options). */
268   bool use_default_partitions;
269   bool use_default_num_partitions;
270   /* Only the number of subpartitions defined (uses default names etc.). */
271   bool use_default_subpartitions;
272   bool use_default_num_subpartitions;
273   bool default_partitions_setup;
274   bool defined_max_value;
has_default_partititon()275   inline bool has_default_partititon()
276   {
277     return (part_type == LIST_PARTITION && defined_max_value);
278   }
279   bool list_of_part_fields;                  // KEY or COLUMNS PARTITIONING
280   bool list_of_subpart_fields;               // KEY SUBPARTITIONING
281   bool linear_hash_ind;                      // LINEAR HASH/KEY
282   bool fixed;
283   bool is_auto_partitioned;
284   bool has_null_value;
285   bool column_list;                          // COLUMNS PARTITIONING, 5.5+
286 
partition_info()287   partition_info()
288   : get_partition_id(NULL), get_part_partition_id(NULL),
289     get_subpartition_id(NULL),
290     part_field_array(NULL), subpart_field_array(NULL),
291     part_charset_field_array(NULL),
292     subpart_charset_field_array(NULL),
293     full_part_field_array(NULL),
294     part_field_buffers(NULL), subpart_field_buffers(NULL),
295     restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL),
296     part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
297     first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL),
298     bitmaps_are_initialized(FALSE),
299     list_array(NULL), vers_info(NULL), err_value(0),
300     part_info_string(NULL),
301     curr_part_elem(NULL), current_partition(NULL),
302     curr_list_object(0), num_columns(0), table(NULL),
303     default_engine_type(NULL),
304     part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
305     part_info_len(0),
306     num_parts(0), num_subparts(0),
307     count_curr_subparts(0),
308     num_list_values(0), num_part_fields(0), num_subpart_fields(0),
309     num_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
310     key_algorithm(KEY_ALGORITHM_NONE),
311     use_default_partitions(TRUE), use_default_num_partitions(TRUE),
312     use_default_subpartitions(TRUE), use_default_num_subpartitions(TRUE),
313     default_partitions_setup(FALSE), defined_max_value(FALSE),
314     list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
315     linear_hash_ind(FALSE), fixed(FALSE),
316     is_auto_partitioned(FALSE),
317     has_null_value(FALSE), column_list(FALSE)
318   {
319     all_fields_in_PF.clear_all();
320     all_fields_in_PPF.clear_all();
321     all_fields_in_SPF.clear_all();
322     some_fields_in_PF.clear_all();
323     partitions.empty();
324     temp_partitions.empty();
325     part_field_list.empty();
326     subpart_field_list.empty();
327   }
~partition_info()328   ~partition_info() {}
329 
330   partition_info *get_clone(THD *thd, bool empty_data_and_index_file= FALSE);
331   bool set_named_partition_bitmap(const char *part_name, size_t length);
332   bool set_partition_bitmaps(List<String> *partition_names);
333   bool set_partition_bitmaps_from_table(TABLE_LIST *table_list);
334   /* Answers the question if subpartitioning is used for a certain table */
is_sub_partitioned()335   bool is_sub_partitioned()
336   {
337     return (subpart_type == NOT_A_PARTITION ?  FALSE : TRUE);
338   }
339 
340   /* Returns the total number of partitions on the leaf level */
get_tot_partitions()341   uint get_tot_partitions()
342   {
343     return num_parts * (is_sub_partitioned() ? num_subparts : 1);
344   }
345 
346   bool set_up_defaults_for_partitioning(THD *thd, handler *file,
347                                         HA_CREATE_INFO *info,
348                                         uint start_no);
349   const char *find_duplicate_field();
350   char *find_duplicate_name();
351   bool check_engine_mix(handlerton *engine_type, bool default_engine);
352   bool check_partition_info(THD *thd, handlerton **eng_type,
353                             handler *file, HA_CREATE_INFO *info,
354                             partition_info *add_or_reorg_part= NULL);
355   void print_no_partition_found(TABLE *table, myf errflag);
356   void print_debug(const char *str, uint*);
357   Item* get_column_item(Item *item, Field *field);
358   int fix_partition_values(THD *thd,
359                            part_elem_value *val,
360                            partition_element *part_elem);
361   bool fix_column_value_functions(THD *thd,
362                                   part_elem_value *val,
363                                   uint part_id);
364   bool fix_parser_data(THD *thd);
365   int add_max_value(THD *thd);
366   void init_col_val(part_column_list_val *col_val, Item *item);
367   int reorganize_into_single_field_col_val(THD *thd);
368   part_column_list_val *add_column_value(THD *thd);
369   bool set_part_expr(THD *thd, Item *item_ptr, bool is_subpart);
370   bool set_up_charset_field_preps(THD *thd);
371   bool check_partition_field_length();
372   bool init_column_part(THD *thd);
373   bool add_column_list_value(THD *thd, Item *item);
374   partition_element *get_part_elem(const char *partition_name, char *file_name,
375                                    size_t file_name_size, uint32 *part_id);
376   void report_part_expr_error(bool use_subpart_expr);
377   bool has_same_partitioning(partition_info *new_part_info);
378   bool error_if_requires_values() const;
379 private:
380   bool set_up_default_partitions(THD *thd, handler *file, HA_CREATE_INFO *info,
381                                  uint start_no);
382   bool set_up_default_subpartitions(THD *thd, handler *file,
383                                     HA_CREATE_INFO *info);
384   char *create_default_partition_names(THD *thd, uint part_no, uint num_parts,
385                                        uint start_no);
386   char *create_default_subpartition_name(THD *thd, uint subpart_no,
387                                          const char *part_name);
388   // FIXME: prune_partition_bitmaps() is duplicate of set_read_partitions()
389   bool prune_partition_bitmaps(List<String> *partition_names);
390   bool add_named_partition(const char *part_name, size_t length);
391 public:
392   bool set_read_partitions(List<char> *partition_names);
393   bool has_unique_name(partition_element *element);
394   bool field_in_partition_expr(Field *field) const;
395 
396   bool vers_init_info(THD *thd);
vers_set_interval(THD * thd,Item * item,interval_type int_type,my_time_t start)397   bool vers_set_interval(THD *thd, Item *item,
398                          interval_type int_type, my_time_t start)
399   {
400     DBUG_ASSERT(part_type == VERSIONING_PARTITION);
401     vers_info->interval.type= int_type;
402     vers_info->interval.start= start;
403     if (item->fix_fields_if_needed_for_scalar(thd, &item))
404       return true;
405     bool error= get_interval_value(thd, item, int_type, &vers_info->interval.step) ||
406            vers_info->interval.step.neg || vers_info->interval.step.second_part ||
407           !(vers_info->interval.step.year || vers_info->interval.step.month ||
408             vers_info->interval.step.day || vers_info->interval.step.hour ||
409             vers_info->interval.step.minute || vers_info->interval.step.second);
410     if (error)
411     {
412       my_error(ER_PART_WRONG_VALUE, MYF(0),
413                thd->lex->create_last_non_select_table->table_name.str,
414                "INTERVAL");
415     }
416     return error;
417   }
vers_set_limit(ulonglong limit)418   bool vers_set_limit(ulonglong limit)
419   {
420     DBUG_ASSERT(part_type == VERSIONING_PARTITION);
421     vers_info->limit= limit;
422     return !limit;
423   }
424   int vers_set_hist_part(THD *thd);
425   bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */
get_partition(uint part_id)426   partition_element *get_partition(uint part_id)
427   {
428     List_iterator<partition_element> it(partitions);
429     partition_element *el;
430     while ((el= it++))
431     {
432       if (el->id == part_id)
433         return el;
434     }
435     return NULL;
436   }
437 };
438 
439 uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
440 bool check_partition_dirs(partition_info *part_info);
441 
442 /* Initialize the iterator to return a single partition with given part_id */
443 
init_single_partition_iterator(uint32 part_id,PARTITION_ITERATOR * part_iter)444 static inline void init_single_partition_iterator(uint32 part_id,
445                                            PARTITION_ITERATOR *part_iter)
446 {
447   part_iter->part_nums.start= part_iter->part_nums.cur= part_id;
448   part_iter->part_nums.end= part_id+1;
449   part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
450   part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE;
451   part_iter->get_next= get_next_partition_id_range;
452 }
453 
454 /* Initialize the iterator to enumerate all partitions */
455 static inline
init_all_partitions_iterator(partition_info * part_info,PARTITION_ITERATOR * part_iter)456 void init_all_partitions_iterator(partition_info *part_info,
457                                   PARTITION_ITERATOR *part_iter)
458 {
459   part_iter->part_nums.start= part_iter->part_nums.cur= 0;
460   part_iter->part_nums.end= part_info->num_parts;
461   part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
462   part_iter->ret_default_part= part_iter->ret_default_part_orig= FALSE;
463   part_iter->get_next= get_next_partition_id_range;
464 }
465 
466 #endif /* PARTITION_INFO_INCLUDED */
467