1 /* Copyright (c) 2013, 2021, Oracle and/or its affiliates.
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 #ifndef PARSE_TREE_HELPERS_INCLUDED
24 #define PARSE_TREE_HELPERS_INCLUDED
25 
26 #include "item_func.h"      // Item etc.
27 #include "set_var.h"        // enum_var_type
28 
29 typedef class st_select_lex SELECT_LEX;
30 
31 /**
32   Base class for parse-time Item objects
33 
34   Parse-time Item objects are placeholders for real Item objects: in some
35   cases it is not easy or even possible to decide what exact Item class object
36   we need to allocate in the parser. Parse-time Item objects are intended
37   to defer real Item object allocation to the contextualization phase (see
38   the Item::itemize() function).
39 
40   This wrapper class overrides abstract virtual functions of the parent
41   class with dummy wrappers to make C++ compiler happy.
42 */
43 class Parse_tree_item : public Item
44 {
45 public:
Parse_tree_item(const POS & pos)46   explicit Parse_tree_item(const POS &pos) : Item(pos) {}
47 
type()48   virtual enum Type type() const { return INVALID_ITEM; }
val_real()49   virtual double val_real() { assert(0); return 0; }
val_int()50   virtual longlong val_int() { assert(0); return 0; }
val_str(String *)51   virtual String *val_str(String *) { assert(0); return NULL; }
val_decimal(my_decimal *)52   virtual my_decimal *val_decimal(my_decimal *) { assert(0); return NULL; }
get_date(MYSQL_TIME *,uint)53   virtual bool get_date(MYSQL_TIME *, uint) { assert(0); return false; }
get_time(MYSQL_TIME *)54   virtual bool get_time(MYSQL_TIME *) { assert(0); return false; }
55 };
56 
57 
58 /**
59   Wrapper class for an Item list head, used to allocate Item lists in the parser
60   in a context-independent way
61 */
62 class PT_item_list : public Parse_tree_node
63 {
64   typedef Parse_tree_node super;
65 
66 public:
67   List<Item> value;
68 
contextualize(Parse_context * pc)69   virtual bool contextualize(Parse_context *pc)
70   {
71     if (super::contextualize(pc))
72       return true;
73     List_iterator<Item> it(value);
74     Item *item;
75     while ((item= it++))
76     {
77       if (item->itemize(pc, &item))
78         return true;
79       it.replace(item);
80     }
81     return false;
82   }
83 
is_empty()84   bool is_empty() const { return value.is_empty(); }
elements()85   uint elements() const { return value.elements; }
86 
87 
push_back(Item * item)88   bool push_back(Item *item)
89   {
90     /*
91      Item may be NULL in case of OOM: just ignore it and check thd->is_error()
92      in the caller code.
93     */
94     return item == NULL || value.push_back(item);
95   }
96 
push_front(Item * item)97   bool push_front(Item *item)
98   {
99     /*
100      Item may be NULL in case of OOM: just ignore it and check thd->is_error()
101      in the caller code.
102     */
103     return item == NULL || value.push_front(item);
104   }
105 
pop_front()106   Item *pop_front()
107   {
108     assert(!is_empty());
109     return value.pop();
110   }
111 };
112 
113 
114 /**
115   Helper function to imitate dynamic_cast for Item_cond hierarchy
116 
117   @param To     destination type (Item_cond_and etc.)
118   @param Tag    Functype tag to compare from->functype() with
119   @param from   source item
120 
121   @return typecasted item of the type To or NULL
122 */
123 template<class To, Item_func::Functype Tag>
item_cond_cast(Item * const from)124 To *item_cond_cast(Item * const from)
125 {
126   return ((from->type() == Item::COND_ITEM &&
127            static_cast<Item_func *>(from)->functype() == Tag) ?
128           static_cast<To *>(from) : NULL);
129 }
130 
131 
132 /**
133   Flatten associative operators at parse time
134 
135   This function flattens AND and OR operators at parse time if applicable,
136   otherwise it creates new Item_cond_and or Item_cond_or respectively.
137 
138   @param Class  Item_cond_and or Item_cond_or
139   @param Tag    COND_AND_FUNC (for Item_cond_and) or COND_OR_FUNC otherwise
140 
141   @param mem_root       MEM_ROOT
142   @param pos            parse location
143   @param left           left argument of the operator
144   @param right          right argument of the operator
145 
146   @return resulting parse tree Item
147 */
148 template<class Class, Item_func::Functype Tag>
flatten_associative_operator(MEM_ROOT * mem_root,const POS & pos,Item * left,Item * right)149 Item *flatten_associative_operator(MEM_ROOT *mem_root, const POS &pos,
150                                    Item *left, Item *right)
151 {
152   if (left == NULL || right == NULL)
153     return NULL;
154   Class *left_func= item_cond_cast<Class, Tag>(left);
155   Class *right_func= item_cond_cast<Class, Tag>(right);
156   if (left_func)
157   {
158     if (right_func)
159     {
160       // (X1 op X2) op (Y1 op Y2) ==> op (X1, X2, Y1, Y2)
161       right_func->add_at_head(left_func->argument_list());
162       return right;
163     }
164     else
165     {
166       // (X1 op X2) op Y ==> op (X1, X2, Y)
167       left_func->add(right);
168       return left;
169     }
170   }
171   else if (right_func)
172   {
173     //  X op (Y1 op Y2) ==> op (X, Y1, Y2)
174     right_func->add_at_head(left);
175     return right;
176   }
177   else
178   {
179     /* X op Y */
180     return new (mem_root) Class(pos, left, right);
181   }
182 }
183 
184 
185 Item_splocal* create_item_for_sp_var(THD *thd,
186                                      LEX_STRING name,
187                                      class sp_variable *spv,
188                                      const char *query_start_ptr,
189                                      const char *start,
190                                      const char *end);
191 
192 bool setup_select_in_parentheses(SELECT_LEX *);
193 void my_syntax_error(const char *s);
194 
195 
196 bool find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp);
197 bool set_system_variable(THD *thd, struct sys_var_with_base *tmp,
198                          enum enum_var_type var_type, Item *val);
199 LEX_STRING make_string(THD *thd, const char *start_ptr, const char *end_ptr);
200 bool set_trigger_new_row(Parse_context *pc,
201                          LEX_STRING trigger_field_name,
202                          Item *expr_item,
203                          LEX_STRING expr_query);
204 void sp_create_assignment_lex(THD *thd, const char *option_ptr);
205 bool sp_create_assignment_instr(THD *thd, const char *expr_end_ptr);
206 
207 #endif /* PARSE_TREE_HELPERS_INCLUDED */
208