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