1 /* Copyright (c) 2013, 2015, 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 #ifndef PARSE_TREE_NODE_INCLUDED
24 #define PARSE_TREE_NODE_INCLUDED
25 
26 #include "my_config.h"
27 #include <cstdlib>
28 #include <cstring>
29 #include "my_sys.h"
30 #include "sql_const.h"
31 
32 #include "parse_location.h"
33 
34 class THD;
35 class st_select_lex;
36 
37 // uncachable cause
38 #define UNCACHEABLE_DEPENDENT   1
39 #define UNCACHEABLE_RAND        2
40 #define UNCACHEABLE_SIDEEFFECT	4
41 /* For uncorrelated SELECT in an UNION with some correlated SELECTs */
42 #define UNCACHEABLE_UNITED      8
43 #define UNCACHEABLE_CHECKOPTION 16
44 
45 /**
46   Names for different query parse tree parts
47 */
48 
49 enum enum_parsing_context
50 {
51   CTX_NONE= 0, ///< Empty value
52   CTX_MESSAGE, ///< "No tables used" messages etc.
53   CTX_TABLE, ///< for single-table UPDATE/DELETE/INSERT/REPLACE
54   CTX_SELECT_LIST, ///< SELECT (subquery), (subquery)...
55   CTX_UPDATE_VALUE_LIST, ///< UPDATE ... SET field=(subquery)...
56   CTX_JOIN,
57   CTX_QEP_TAB,
58   CTX_MATERIALIZATION,
59   CTX_DUPLICATES_WEEDOUT,
60   CTX_DERIVED, ///< "Derived" subquery
61   CTX_WHERE, ///< Subquery in WHERE clause item tree
62   CTX_ON,    ///< ON clause context
63   CTX_HAVING, ///< Subquery in HAVING clause item tree
64   CTX_ORDER_BY, ///< ORDER BY clause execution context
65   CTX_GROUP_BY, ///< GROUP BY clause execution context
66   CTX_SIMPLE_ORDER_BY, ///< ORDER BY clause execution context
67   CTX_SIMPLE_GROUP_BY, ///< GROUP BY clause execution context
68   CTX_DISTINCT, ///< DISTINCT clause execution context
69   CTX_SIMPLE_DISTINCT, ///< DISTINCT clause execution context
70   CTX_BUFFER_RESULT, ///< see SQL_BUFFER_RESULT in the manual
71   CTX_ORDER_BY_SQ, ///< Subquery in ORDER BY clause item tree
72   CTX_GROUP_BY_SQ, ///< Subquery in GROUP BY clause item tree
73   CTX_OPTIMIZED_AWAY_SUBQUERY, ///< Subquery executed once during optimization
74   CTX_UNION,
75   CTX_UNION_RESULT, ///< Pseudo-table context for UNION result
76   CTX_QUERY_SPEC ///< Inner SELECTs of UNION expression
77 };
78 
79 /*
80   Note: YYLTYPE doesn't overload a default constructor (as well an underlying
81   Symbol_location).
82   OTOH if we need a zero-initialized POS, YYLTYPE or Symbol_location object,
83   we can simply call POS(), YYLTYPE() or Symbol_location(): C++ does
84   value-initialization in that case.
85 */
86 typedef YYLTYPE POS;
87 
88 /**
89   Environment data for the contextualization phase
90 */
91 struct Parse_context {
92   THD * const thd;              ///< Current thread handler
93   MEM_ROOT *mem_root;           ///< Current MEM_ROOT
94   st_select_lex * select;       ///< Current SELECT_LEX object
95 
96   Parse_context(THD *thd, st_select_lex *select);
97 };
98 
99 
100 // defined in sql_parse.cc:
101 bool check_stack_overrun(THD *thd, long margin, uchar *dummy);
102 
103 
104 /**
105   Base class for parse tree nodes
106 */
107 class Parse_tree_node
108 {
109   friend class Item; // for direct access to the "contextualized" field
110 
111   Parse_tree_node(const Parse_tree_node &); // undefined
112   void operator=(const Parse_tree_node &); // undefined
113 
114 #ifndef DBUG_OFF
115 private:
116   bool contextualized; // true if the node object is contextualized
117   bool transitional; // TODO: remove that after parser refactoring
118 #endif//DBUG_OFF
119 
120 public:
new(size_t size,MEM_ROOT * mem_root)121   static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
122   { return alloc_root(mem_root, size); }
delete(void * ptr,size_t size)123   static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
delete(void * ptr,MEM_ROOT * mem_root)124   static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
125 
126 protected:
Parse_tree_node()127   Parse_tree_node()
128   {
129 #ifndef DBUG_OFF
130     contextualized= false;
131     transitional= false;
132 #endif//DBUG_OFF
133   }
134 
135 public:
~Parse_tree_node()136   virtual ~Parse_tree_node() {}
137 
138 #ifndef DBUG_OFF
is_contextualized()139   bool is_contextualized() const { return contextualized; }
140 #endif//DBUG_OFF
141 
142   /**
143     Do all context-sensitive things and mark the node as contextualized
144 
145     @param      pc      current parse context
146 
147     @retval     false   success
148     @retval     true    syntax/OOM/etc error
149   */
contextualize(Parse_context * pc)150   virtual bool contextualize(Parse_context *pc)
151   {
152 #ifndef DBUG_OFF
153     if (transitional)
154     {
155       DBUG_ASSERT(contextualized);
156       return false;
157     }
158 #endif//DBUG_OFF
159 
160     uchar dummy;
161     if (check_stack_overrun(pc->thd, STACK_MIN_SIZE, &dummy))
162       return true;
163 
164 #ifndef DBUG_OFF
165     DBUG_ASSERT(!contextualized);
166     contextualized= true;
167 #endif//DBUG_OFF
168 
169     return false;
170   }
171 
172   /**
173    Intermediate version of the contextualize() function
174 
175    This function is intended to resolve parser grammar loops.
176 
177     During the step-by-step refactoring of the parser grammar we wrap
178     each context-sensitive semantic action with 3 calls:
179     1. Parse_tree_node() context-independent constructor call,
180     2. contextualize_() function call to evaluate all context-sensitive things
181        from the former context-sensitive semantic action code.
182     3. Call of dummy contextualize() function.
183 
184     Then we lift the contextualize() function call to outer grammar rules but
185     save the contextualize_() function call untouched.
186 
187     When all loops in the grammar rules are resolved (i.e. transformed
188     as described above) we:
189     a. remove all contextualize_() function calls and
190     b. rename all contextualize_() function definitions to contextualize()
191        function definitions.
192 
193     Note: it's not necessary to transform the whole grammar and remove
194     this function calls in one pass: it's possible to transform the
195     grammar statement by statement in a way described above.
196 
197     Note: remove this function together with Item::contextualize_().
198   */
contextualize_(Parse_context * pc)199   virtual bool contextualize_(Parse_context *pc)
200   {
201 #ifndef DBUG_OFF
202     DBUG_ASSERT(!contextualized && !transitional);
203     transitional= true;
204     contextualized= true;
205 #endif//DBUG_OFF
206     return false;
207   }
208 
209   void error(Parse_context *pc,
210              const POS &position,
211              const char * msg= NULL) const;
212 };
213 
214 #endif /* PARSE_TREE_NODE_INCLUDED */
215