1 /* Copyright (c) 2016, 2019, 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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include "sql/parse_tree_partitions.h"
24 
25 #include "m_ctype.h"
26 #include "my_dbug.h"
27 #include "my_sys.h"
28 #include "mysql_com.h"
29 #include "mysqld_error.h"
30 #include "sql/derror.h"
31 #include "sql/item.h"
32 #include "sql/parse_location.h"
33 #include "sql/sql_class.h"
34 #include "sql/sql_const.h"
35 #include "sql/sql_lex.h"
36 #include "sql/sql_list.h"
37 #include "sql/sql_parse.h"
38 #include "sql_string.h"
39 
Partition_parse_context(THD * thd_arg,partition_info * part_info_arg,partition_element * current_partition_arg,partition_element * curr_part_elem_arg,bool is_add_or_reorganize_partition)40 Partition_parse_context::Partition_parse_context(
41     THD *thd_arg, partition_info *part_info_arg,
42     partition_element *current_partition_arg,
43     partition_element *curr_part_elem_arg, bool is_add_or_reorganize_partition)
44     : Parse_context(thd_arg, thd_arg->lex->current_select()),
45       Parser_partition_info(part_info_arg, current_partition_arg,
46                             curr_part_elem_arg, nullptr, 0),
47       is_add_or_reorganize_partition(is_add_or_reorganize_partition) {}
48 
contextualize(Partition_parse_context * pc)49 bool PT_subpartition::contextualize(Partition_parse_context *pc) {
50   partition_info *const part_info = pc->part_info;
51 
52   if (part_info->use_default_subpartitions &&
53       part_info->partitions.elements >= 2) {
54     /*
55       create table t1 (a int)
56       partition by list (a) subpartition by hash (a)
57       (partition p0 values in (1),
58        partition p1 values in (2) subpartition sp11);
59       causes us to arrive since we are on the second
60       partition, but still use_default_subpartitions
61       is set. When we come here we're processing at least
62       the second partition (the current partition processed
63       have already been put into the partitions list.
64     */
65     error(pc, pos, ER_THD(pc->thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR));
66     return true;
67   }
68 
69   auto *sub_p_elem =
70       new (pc->mem_root) partition_element(pc->current_partition);
71   if (sub_p_elem == nullptr) return true;
72 
73   if (check_string_char_length(to_lex_cstring(name), "", NAME_CHAR_LEN,
74                                system_charset_info, true)) {
75     my_error(ER_TOO_LONG_IDENT, MYF(0), name);
76     return true;
77   }
78 
79   sub_p_elem->partition_name = name;
80 
81   part_info->use_default_subpartitions = false;
82   part_info->use_default_num_subpartitions = false;
83   pc->count_curr_subparts++;
84 
85   Partition_parse_context subpart_pc(pc->thd, part_info, pc->current_partition,
86                                      sub_p_elem,
87                                      pc->is_add_or_reorganize_partition);
88 
89   if (options != nullptr) {
90     for (auto option : *options) {
91       if (option->contextualize(&subpart_pc)) return true;
92     }
93     if (sub_p_elem->engine_type != nullptr)
94       part_info->default_engine_type = sub_p_elem->engine_type;
95   }
96   if (pc->current_partition->subpartitions.push_back(sub_p_elem)) return true;
97 
98   return false;
99 }
100 
contextualize(Partition_parse_context * pc)101 bool PT_part_value_item_max::contextualize(Partition_parse_context *pc) {
102   if (super::contextualize(pc)) return true;
103 
104   if (pc->part_info->part_type == partition_type::LIST) {
105     error(pc, pos, ER_THD(pc->thd, ER_MAXVALUE_IN_VALUES_IN));
106     return true;
107   }
108   if (pc->add_max_value()) return true;
109 
110   return false;
111 }
112 
contextualize(Partition_parse_context * pc)113 bool PT_part_value_item_expr::contextualize(Partition_parse_context *pc) {
114   if (super::contextualize(pc) || expr->itemize(pc, &expr)) return true;
115 
116   if (!pc->thd->lex->safe_to_cache_query) {
117     error(pc, pos, ER_THD(pc->thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
118     return true;
119   }
120   if (pc->add_column_list_value(pc->thd, expr)) return true;
121 
122   return false;
123 }
124 
contextualize(Partition_parse_context * pc)125 bool PT_part_value_item_list_paren::contextualize(Partition_parse_context *pc) {
126   pc->part_info->print_debug("( part_value_item_list_paren", nullptr);
127   /* Initialisation code needed for each list of value expressions */
128   if (!(pc->part_info->part_type == partition_type::LIST &&
129         pc->part_info->num_columns == 1U) &&
130       pc->init_column_part()) {
131     return true;
132   }
133 
134   for (auto value : *values) {
135     if (value->contextualize(pc)) return true;
136   }
137 
138   pc->part_info->print_debug(") part_value_item_list_paren", nullptr);
139   if (pc->part_info->num_columns == 0)
140     pc->part_info->num_columns = pc->curr_list_object;
141   if (pc->part_info->num_columns != pc->curr_list_object) {
142     /*
143       All value items lists must be of equal length, in some cases
144       which is covered by the above if-statement we don't know yet
145       how many columns is in the partition so the assignment above
146       ensures that we only report errors when we know we have an
147       error.
148     */
149     pc->part_info->print_debug("Kilroy I", nullptr);
150     error(pc, paren_pos, ER_THD(pc->thd, ER_PARTITION_COLUMN_LIST_ERROR));
151     return true;
152   }
153   pc->curr_list_object = 0;
154   return false;
155 }
156 
contextualize(Partition_parse_context * pc)157 bool PT_part_values_in_item::contextualize(Partition_parse_context *pc) {
158   if (super::contextualize(pc) || item->contextualize(pc)) return true;
159 
160   partition_info *const part_info = pc->part_info;
161   part_info->print_debug("part_values_in: part_value_item_list_paren", nullptr);
162 
163   if (part_info->num_columns != 1U) {
164     if (!pc->is_add_or_reorganize_partition || part_info->num_columns == 0 ||
165         part_info->num_columns > MAX_REF_PARTS) {
166       part_info->print_debug("Kilroy III", nullptr);
167       error(pc, pos, ER_THD(pc->thd, ER_PARTITION_COLUMN_LIST_ERROR));
168       return true;
169     }
170     /*
171       Reorganize the current large array into a list of small
172       arrays with one entry in each array. This can happen
173       in the first partition of an ALTER TABLE statement where
174       we ADD or REORGANIZE partitions. Also can only happen
175       for LIST [COLUMNS] partitions.
176     */
177     if (pc->reorganize_into_single_field_col_val()) return true;
178   }
179   return false;
180 }
181 
contextualize(Partition_parse_context * pc)182 bool PT_part_values_in_list::contextualize(Partition_parse_context *pc) {
183   if (super::contextualize(pc)) return true;
184 
185   for (auto item : *list) {
186     if (item->contextualize(pc)) return true;
187   }
188 
189   if (pc->part_info->num_columns < 2U) {
190     error(pc, pos, ER_THD(pc->thd, ER_ROW_SINGLE_PARTITION_FIELD_ERROR));
191     return true;
192   }
193   return false;
194 }
195 
contextualize(Partition_parse_context * pc)196 bool PT_part_definition::contextualize(Partition_parse_context *pc) {
197   DBUG_ASSERT(pc->current_partition == nullptr &&
198               pc->curr_part_elem == nullptr);
199 
200   if (super::contextualize(pc)) return true;
201 
202   partition_info *const part_info = pc->part_info;
203 
204   auto *const curr_part = new (pc->thd->mem_root) partition_element();
205   if (curr_part == nullptr) return true;
206 
207   Partition_parse_context ppc(pc->thd, part_info, curr_part, curr_part,
208                               pc->is_add_or_reorganize_partition);
209 
210   if (!curr_part || part_info->partitions.push_back(curr_part)) return true;
211   curr_part->part_state = PART_NORMAL;
212   part_info->use_default_partitions = false;
213   part_info->use_default_num_partitions = false;
214 
215   if (check_string_char_length(to_lex_cstring(name), "", NAME_CHAR_LEN,
216                                system_charset_info, true)) {
217     my_error(ER_TOO_LONG_IDENT, MYF(0), name.str);
218     return true;
219   }
220 
221   curr_part->partition_name = name.str;
222 
223   switch (type) {
224     case partition_type::HASH: {
225       if (part_info->part_type == partition_type::NONE)
226         part_info->part_type = partition_type::HASH;
227       else if (part_info->part_type == partition_type::RANGE) {
228         errorf(&ppc, pos, ER_THD(pc->thd, ER_PARTITION_REQUIRES_VALUES_ERROR),
229                "RANGE", "LESS THAN");
230         return true;
231       } else if (part_info->part_type == partition_type::LIST) {
232         errorf(&ppc, pos, ER_THD(pc->thd, ER_PARTITION_REQUIRES_VALUES_ERROR),
233                "LIST", "IN");
234         return true;
235       }
236     } break;
237     case partition_type::RANGE: {
238       if (part_info->part_type == partition_type::NONE)
239         part_info->part_type = partition_type::RANGE;
240       else if (part_info->part_type != partition_type::RANGE) {
241         my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
242         return true;
243       }
244 
245       if (opt_part_values == nullptr)  // MAX_VALUE_SYM
246       {
247         if (part_info->num_columns && part_info->num_columns != 1U) {
248           part_info->print_debug("Kilroy II", nullptr);
249           error(&ppc, values_pos,
250                 ER_THD(pc->thd, ER_PARTITION_COLUMN_LIST_ERROR));
251           return true;
252         } else
253           part_info->num_columns = 1U;
254         if (ppc.init_column_part() || ppc.add_max_value()) return true;
255       } else if (opt_part_values->contextualize(&ppc))
256         return true;
257     } break;
258     case partition_type::LIST: {
259       if (part_info->part_type == partition_type::NONE)
260         part_info->part_type = partition_type::LIST;
261       else if (part_info->part_type != partition_type::LIST) {
262         my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), "LIST", "IN");
263         return true;
264       }
265 
266       if (opt_part_values->contextualize(&ppc)) return true;
267     } break;
268     default:
269       DBUG_ASSERT(false);
270       error(&ppc, pos, ER_THD(pc->thd, ER_UNKNOWN_ERROR));
271       return true;
272   }
273 
274   if (opt_part_options != nullptr) {
275     for (auto option : *opt_part_options) {
276       if (option->contextualize(&ppc)) return true;
277     }
278     if (curr_part->engine_type != nullptr)
279       part_info->default_engine_type = curr_part->engine_type;
280   }
281 
282   if (opt_sub_partitions == nullptr) {
283     if (part_info->num_subparts != 0 && !part_info->use_default_subpartitions) {
284       /*
285         We come here when we have defined subpartitions on the first
286         partition but not on all the subsequent partitions.
287       */
288       error(&ppc, sub_partitions_pos,
289             ER_THD(pc->thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR));
290       return true;
291     }
292   } else {
293     for (auto subpartition : *opt_sub_partitions) {
294       if (subpartition->contextualize(&ppc)) return true;
295     }
296 
297     if (part_info->num_subparts != 0) {
298       if (part_info->num_subparts != ppc.count_curr_subparts) {
299         error(&ppc, sub_partitions_pos,
300               ER_THD(pc->thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR));
301         return true;
302       }
303     } else if (ppc.count_curr_subparts > 0) {
304       if (part_info->partitions.elements > 1) {
305         error(&ppc, sub_partitions_pos,
306               ER_THD(pc->thd, ER_PARTITION_WRONG_NO_SUBPART_ERROR));
307         return true;
308       }
309       part_info->num_subparts = ppc.count_curr_subparts;
310     }
311   }
312   return false;
313 }
314 
contextualize(Partition_parse_context * pc)315 bool PT_sub_partition_by_hash::contextualize(Partition_parse_context *pc) {
316   if (super::contextualize(pc) || hash->itemize(pc, &hash)) return true;
317 
318   partition_info *const part_info = pc->part_info;
319 
320   part_info->subpart_type = partition_type::HASH;
321   part_info->linear_hash_ind = is_linear;
322 
323   LEX *const lex = pc->thd->lex;
324   if (!lex->safe_to_cache_query) {
325     error(pc, hash_pos, ER_THD(pc->thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
326     return true;
327   }
328   lex->safe_to_cache_query = true;
329 
330   /* TODO: remove const_cast */
331   if (part_info->set_part_expr(const_cast<char *>(hash_pos.cpp.start), hash,
332                                const_cast<char *>(hash_pos.cpp.end), true))
333     return true;
334 
335   if (opt_num_subparts > 0) {
336     part_info->num_subparts = opt_num_subparts;
337     part_info->use_default_num_subpartitions = false;
338   }
339   return false;
340 }
341 
contextualize(Partition_parse_context * pc)342 bool PT_sub_partition_by_key::contextualize(Partition_parse_context *pc) {
343   if (super::contextualize(pc)) return true;
344 
345   partition_info *const part_info = pc->part_info;
346 
347   part_info->subpart_type = partition_type::HASH;
348   part_info->list_of_subpart_fields = true;
349 
350   part_info->linear_hash_ind = is_linear;
351   part_info->key_algorithm = key_algo;
352 
353   if (field_names->elements > MAX_REF_PARTS) {
354     my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
355              "list of subpartition fields");
356     return true;
357   }
358   part_info->subpart_field_list = *field_names;
359 
360   if (opt_num_subparts > 0) {
361     part_info->num_subparts = opt_num_subparts;
362     part_info->use_default_num_subpartitions = false;
363   }
364   return false;
365 }
366 
set_part_field_list(Partition_parse_context * pc,List<char> * list)367 bool PT_part_type_def::set_part_field_list(Partition_parse_context *pc,
368                                            List<char> *list) {
369   if (list->elements > MAX_REF_PARTS) {
370     my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
371              "list of partition fields");
372     return true;
373   }
374   pc->part_info->num_columns = list->elements;
375   pc->part_info->part_field_list = *list;
376   return false;
377 }
378 
itemize_part_expr(Partition_parse_context * pc,const POS & pos,Item ** item)379 bool PT_part_type_def::itemize_part_expr(Partition_parse_context *pc,
380                                          const POS &pos, Item **item) {
381   if ((*item)->itemize(pc, item)) return true;
382 
383   if (!pc->thd->lex->safe_to_cache_query) {
384     error(pc, pos, ER_THD(pc->thd, ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
385     return true;
386   }
387   pc->thd->lex->safe_to_cache_query = true;
388 
389   if (pc->part_info->set_part_expr(const_cast<char *>(pos.cpp.start), *item,
390                                    const_cast<char *>(pos.cpp.end), false))
391     return true;
392 
393   return false;
394 }
395 
contextualize(Partition_parse_context * pc)396 bool PT_part_type_def_key::contextualize(Partition_parse_context *pc) {
397   if (super::contextualize(pc)) return true;
398 
399   pc->part_info->part_type = partition_type::HASH;
400   pc->part_info->column_list = false;
401   pc->part_info->key_algorithm = key_algo;
402   pc->part_info->linear_hash_ind = is_linear;
403   pc->part_info->list_of_part_fields = true;
404 
405   if (opt_columns != nullptr && set_part_field_list(pc, opt_columns))
406     return true;
407 
408   return false;
409 }
410 
contextualize(Partition_parse_context * pc)411 bool PT_part_type_def_hash::contextualize(Partition_parse_context *pc) {
412   if (super::contextualize(pc) || itemize_part_expr(pc, expr_pos, &expr))
413     return true;
414 
415   pc->part_info->part_type = partition_type::HASH;
416   pc->part_info->column_list = false;
417   pc->part_info->linear_hash_ind = is_linear;
418   pc->part_info->num_columns = 1;
419 
420   return false;
421 }
422 
contextualize(Partition_parse_context * pc)423 bool PT_part_type_def_range_expr::contextualize(Partition_parse_context *pc) {
424   if (super::contextualize(pc) || itemize_part_expr(pc, expr_pos, &expr))
425     return true;
426 
427   pc->part_info->part_type = partition_type::RANGE;
428   pc->part_info->column_list = false;
429   pc->part_info->num_columns = 1;
430 
431   return false;
432 }
433 
contextualize(Partition_parse_context * pc)434 bool PT_part_type_def_range_columns::contextualize(
435     Partition_parse_context *pc) {
436   if (super::contextualize(pc)) return true;
437 
438   pc->part_info->part_type = partition_type::RANGE;
439   pc->part_info->column_list = true;
440   pc->part_info->list_of_part_fields = true;
441 
442   return set_part_field_list(pc, columns);
443 }
444 
contextualize(Partition_parse_context * pc)445 bool PT_part_type_def_list_expr::contextualize(Partition_parse_context *pc) {
446   if (super::contextualize(pc) || itemize_part_expr(pc, expr_pos, &expr))
447     return true;
448 
449   pc->part_info->part_type = partition_type::LIST;
450   pc->part_info->column_list = false;
451   pc->part_info->num_columns = 1;
452 
453   return false;
454 }
455 
contextualize(Partition_parse_context * pc)456 bool PT_part_type_def_list_columns::contextualize(Partition_parse_context *pc) {
457   if (super::contextualize(pc)) return true;
458 
459   pc->part_info->part_type = partition_type::LIST;
460   pc->part_info->column_list = true;
461   pc->part_info->list_of_part_fields = true;
462 
463   return set_part_field_list(pc, columns);
464 }
465 
contextualize(Parse_context * pc)466 bool PT_partition::contextualize(Parse_context *pc) {
467   if (super::contextualize(pc)) return true;
468 
469   Partition_parse_context part_pc(pc->thd, &part_info, false);
470   if (part_type_def->contextualize(&part_pc)) return true;
471 
472   if (opt_num_parts != 0) {
473     part_info.num_parts = opt_num_parts;
474     part_info.use_default_num_partitions = false;
475   }
476 
477   if (opt_sub_part != nullptr && opt_sub_part->contextualize(&part_pc))
478     return true;
479 
480   if (part_defs == nullptr) {
481     if (part_info.part_type == partition_type::RANGE) {
482       my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), "RANGE");
483       return true;
484     } else if (part_info.part_type == partition_type::LIST) {
485       my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), "LIST");
486       return true;
487     }
488   } else {
489     for (auto part_def : *part_defs) {
490       if (part_def->contextualize(&part_pc)) return true;
491     }
492     uint count_curr_parts = part_info.partitions.elements;
493 
494     if (part_info.num_parts != 0) {
495       if (part_info.num_parts != count_curr_parts) {
496         error(&part_pc, part_defs_pos,
497               ER_THD(pc->thd, ER_PARTITION_WRONG_NO_PART_ERROR));
498         return true;
499       }
500     } else if (count_curr_parts > 0)
501       part_info.num_parts = count_curr_parts;
502   }
503   return false;
504 }
505