1 /* Copyright (c) 2015, 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
24 #include "sql_show_status.h"
25 #include "sql_parse.h"
26 #include "sql_yacc.h"
27 #include "parse_tree_items.h"
28 #include "parse_tree_nodes.h"
29 #include "item_cmpfunc.h"
30
31 /**
32 Build a replacement query for SHOW STATUS.
33 When the parser accepts the following syntax:
34 SHOW GLOBAL STATUS
35 the parsed tree built for this query is in fact:
36 SELECT * FROM
37 (SELECT VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value
38 FROM performance_schema.global_status) global_status
39
40 Likewise, the query:
41 SHOW GLOBAL STATUS LIKE "<value>"
42 is built as:
43 SELECT * FROM
44 (SELECT VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value
45 FROM performance_schema.global_status) global_status
46 WHERE Variable_name LIKE "<value>"
47
48 Likewise, the query:
49 SHOW GLOBAL STATUS where <where_clause>
50 is built as:
51 SELECT * FROM
52 (SELECT VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value
53 FROM performance_schema.global_status) global_status
54 WHERE <where_clause>
55 */
56 SELECT_LEX*
build_query(const POS & pos,THD * thd,enum_sql_command command,const LEX_STRING & table_name,const String * wild,Item * where_cond)57 build_query(const POS &pos,
58 THD *thd,
59 enum_sql_command command,
60 const LEX_STRING& table_name,
61 const String *wild,
62 Item *where_cond)
63 {
64 /*
65 MAINTAINER:
66 This code builds a parsed tree for a query.
67 Write the query to build in SQL first,
68 then see turn_parser_debug_on() in sql_yacc.yy
69 to understand which grammar actions are needed to
70 build a parsed tree for this SQL query.
71 */
72 static const LEX_STRING col_name= { C_STRING_WITH_LEN("VARIABLE_NAME")};
73 static const LEX_STRING as_name= { C_STRING_WITH_LEN("Variable_name")};
74 static const LEX_STRING col_value= { C_STRING_WITH_LEN("VARIABLE_VALUE")};
75 static const LEX_STRING as_value= { C_STRING_WITH_LEN("Value")};
76 static const LEX_STRING pfs= { C_STRING_WITH_LEN("performance_schema")};
77
78 static const Query_options options=
79 {
80 0, /* query_spec_options */
81 SELECT_LEX::SQL_CACHE_UNSPECIFIED /* sql_cache */
82 };
83
84 static const Select_lock_type lock_type=
85 {
86 false, /* is_set */
87 TL_READ, /* lock_type */
88 false /* is_safe_to_cache_query */
89 };
90
91
92 /* * */
93 Item *star= new (thd->mem_root) Item_asterisk(pos, NULL, NULL);
94
95 PT_select_item_list *item_list2;
96 item_list2= new (thd->mem_root) PT_select_item_list();
97 if (item_list2 == NULL)
98 return NULL;
99 item_list2->push_back(star);
100
101 /* SELECT * ... */
102 PT_select_options_and_item_list *options_and_item_list2;
103 options_and_item_list2= new (thd->mem_root) PT_select_options_and_item_list(options, item_list2);
104 if (options_and_item_list2 == NULL)
105 return NULL;
106
107
108 /*
109 ... (SELECT VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value
110 FROM performance_schema.<table_name>) ...
111 */
112
113 /* ... VARIABLE_NAME ... */
114 PTI_simple_ident_ident *ident_name;
115 ident_name= new (thd->mem_root) PTI_simple_ident_ident(pos, col_name);
116 if (ident_name == NULL)
117 return NULL;
118
119 /* ... VARIABLE_NAME as Variable_name ... */
120 PTI_expr_with_alias *expr_name;
121 expr_name= new (thd->mem_root) PTI_expr_with_alias(pos, ident_name, pos.cpp, as_name);
122 if (expr_name == NULL)
123 return NULL;
124
125 /* ... VARIABLE_VALUE ... */
126 PTI_simple_ident_ident *ident_value;
127 ident_value= new (thd->mem_root) PTI_simple_ident_ident(pos, col_value);
128 if (ident_value == NULL)
129 return NULL;
130
131 /* ... VARIABLE_VALUE as Value ... */
132 PTI_expr_with_alias *expr_value;
133 expr_value= new (thd->mem_root) PTI_expr_with_alias(pos, ident_value, pos.cpp, as_value);
134 if (expr_value == NULL)
135 return NULL;
136
137 /* ... VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value ... */
138 PT_select_item_list *item_list;
139 item_list= new (thd->mem_root) PT_select_item_list();
140 if (item_list == NULL)
141 return NULL;
142 item_list->push_back(expr_name);
143 item_list->push_back(expr_value);
144
145 /* SELECT VARIABLE_NAME as Variable_name, VARIABLE_VALUE as Value ... */
146 PT_select_options_and_item_list *options_and_item_list;
147 options_and_item_list= new (thd->mem_root) PT_select_options_and_item_list(options, item_list);
148 if (options_and_item_list == NULL)
149 return NULL;
150
151 /*
152 make_table_list() might alter the database and table name strings. Create
153 copies and leave the original values unaltered.
154 */
155
156 /* ... performance_schema ... */
157 LEX_CSTRING tmp_db_name;
158 if (!thd->make_lex_string(&tmp_db_name, pfs.str, pfs.length, false))
159 return NULL;
160
161 /* ... <table_name> ... */
162 LEX_CSTRING tmp_table_name;
163 if (!thd->make_lex_string(&tmp_table_name, table_name.str, table_name.length, false))
164 return NULL;
165
166 /* ... performance_schema.<table_name> ... */
167 Table_ident *table_ident;
168 table_ident= new (thd->mem_root) Table_ident(tmp_db_name, tmp_table_name);
169 if (table_ident == NULL)
170 return NULL;
171
172 /* ... FROM performance_schema.<table_name> ... */
173 PT_table_factor_table_ident *table_factor;
174 table_factor= new (thd->mem_root) PT_table_factor_table_ident(table_ident, NULL, NULL, NULL);
175 if (table_factor == NULL)
176 return NULL;
177
178 PT_join_table_list *join_table_list;
179 join_table_list= new (thd->mem_root) PT_join_table_list(pos, table_factor);
180 if (join_table_list == NULL)
181 return NULL;
182
183 PT_table_reference_list *table_reference_list;
184 table_reference_list= new (thd->mem_root) PT_table_reference_list(join_table_list);
185 if (table_reference_list == NULL)
186 return NULL;
187
188 PT_table_expression *table_expression;
189 table_expression= new (thd->mem_root)PT_table_expression(table_reference_list,
190 NULL,
191 NULL,
192 NULL,
193 NULL,
194 NULL,
195 NULL,
196 lock_type);
197
198 /* ... FROM (SELECT ...) ... */
199 PT_table_factor_select_sym *table_factor_select_sym;
200 table_factor_select_sym= new (thd->mem_root) PT_table_factor_select_sym(pos, NULL, options, item_list, table_expression);
201 if (table_factor_select_sym == NULL)
202 return NULL;
203
204 PT_select_derived *select_derived;
205 select_derived= new (thd->mem_root) PT_select_derived(pos, table_factor_select_sym);
206 if (select_derived == NULL)
207 return NULL;
208
209 PT_select_derived_union_select *select_derived_union_select;
210 select_derived_union_select= new (thd->mem_root) PT_select_derived_union_select(select_derived, NULL, pos);
211 if (select_derived_union_select == NULL)
212 return NULL;
213
214 /* ... derived_table ... */
215 LEX_STRING derived_table_name;
216 if (!thd->make_lex_string(&derived_table_name, table_name.str, table_name.length, false))
217 return NULL;
218
219 PT_table_factor_parenthesis *table_factor_parenthesis;
220 table_factor_parenthesis= new (thd->mem_root) PT_table_factor_parenthesis(select_derived_union_select, &derived_table_name, pos);
221 if (table_factor_parenthesis == NULL)
222 return NULL;
223
224 PT_join_table_list *join_table_list2;
225 join_table_list2= new (thd->mem_root) PT_join_table_list(pos, table_factor_parenthesis);
226 if (join_table_list2 == NULL)
227 return NULL;
228
229 PT_table_reference_list *table_reference_list2;
230 table_reference_list2= new (thd->mem_root) PT_table_reference_list(join_table_list2);
231 if (table_reference_list2 == NULL)
232 return NULL;
233
234 /* where clause */
235 Item *where_clause= NULL;
236
237 if (wild != NULL)
238 {
239 /* ... Variable_name ... */
240 PTI_simple_ident_ident *ident_name_where;
241 ident_name_where= new (thd->mem_root) PTI_simple_ident_ident(pos, as_name);
242 if (ident_name_where == NULL)
243 return NULL;
244
245 /* ... <value> ... */
246 LEX_STRING *lex_string;
247 lex_string= static_cast<LEX_STRING*> (thd->alloc(sizeof(LEX_STRING)));
248 if (lex_string == NULL)
249 return NULL;
250 lex_string->length= wild->length();
251 lex_string->str= thd->strmake(wild->ptr(), wild->length());
252 if (lex_string->str == NULL)
253 return NULL;
254
255 PTI_text_literal_text_string *wild_string;
256 wild_string= new (thd->mem_root) PTI_text_literal_text_string(pos, false, *lex_string); // TODO WL#6629 check is_7bit
257 if (wild_string == NULL)
258 return NULL;
259
260 /* ... Variable_name LIKE <value> ... */
261 Item_func_like *func_like;
262 func_like= new (thd->mem_root) Item_func_like(pos, ident_name_where, wild_string, NULL);
263 if (func_like == NULL)
264 return NULL;
265
266 /* ... WHERE Variable_name LIKE <value> ... */
267 where_clause= new (thd->mem_root) PTI_context<CTX_WHERE>(pos, func_like);
268 if (where_clause == NULL)
269 return NULL;
270 }
271 else
272 {
273 where_clause= where_cond;
274 }
275
276
277 /* SELECT * FROM (SELECT ...) derived_table [ WHERE Variable_name LIKE <value> ] */
278 /* SELECT * FROM (SELECT ...) derived_table [ WHERE <cond> ] */
279 PT_select_part2 *select_part2;
280 select_part2= new (thd->mem_root) PT_select_part2(options_and_item_list2,
281 NULL, /* opt_into */
282 table_reference_list2, /* from_clause */
283 where_clause, /* opt_where_clause */
284 NULL, /* opt_group_clause */
285 NULL, /* opt_having_clause */
286 NULL, /* opt_order_clause */
287 NULL, /* opt_limit_clause */
288 NULL, /* opt_procedure_analyse_clause */
289 NULL, /* opt_into */
290 lock_type /* opt_select_lock_type */);
291 if (select_part2 == NULL)
292 return NULL;
293
294 PT_select_init2 *select_init2;
295 select_init2= new (thd->mem_root) PT_select_init2(NULL, select_part2, NULL);
296 if (select_init2 == NULL)
297 return NULL;
298
299 PT_select *select;
300 select= new (thd->mem_root) PT_select(select_init2, SQLCOM_SELECT);
301 if (select == NULL)
302 return NULL;
303
304 LEX *lex= thd->lex;
305 SELECT_LEX *current_select= lex->current_select();
306 Parse_context pc(thd, current_select);
307 if (thd->is_error())
308 return NULL;
309
310 if (select->contextualize(&pc))
311 return NULL;
312
313 /* contextualize sets to COM_SELECT */
314 lex->sql_command= command;
315
316 return current_select;
317 }
318
319 SELECT_LEX*
build_show_session_status(const POS & pos,THD * thd,const String * wild,Item * where_cond)320 build_show_session_status(const POS &pos, THD *thd, const String *wild, Item *where_cond)
321 {
322 static const LEX_STRING table_name= { C_STRING_WITH_LEN("session_status")};
323
324 return build_query(pos, thd, SQLCOM_SHOW_STATUS, table_name, wild, where_cond);
325 }
326
327 SELECT_LEX*
build_show_global_status(const POS & pos,THD * thd,const String * wild,Item * where_cond)328 build_show_global_status(const POS &pos, THD *thd, const String *wild, Item *where_cond)
329 {
330 static const LEX_STRING table_name= { C_STRING_WITH_LEN("global_status")};
331
332 return build_query(pos, thd, SQLCOM_SHOW_STATUS, table_name, wild, where_cond);
333 }
334
335 SELECT_LEX*
build_show_session_variables(const POS & pos,THD * thd,const String * wild,Item * where_cond)336 build_show_session_variables(const POS &pos, THD *thd, const String *wild, Item *where_cond)
337 {
338 static const LEX_STRING table_name= { C_STRING_WITH_LEN("session_variables")};
339
340 return build_query(pos, thd, SQLCOM_SHOW_VARIABLES, table_name, wild, where_cond);
341 }
342
343 SELECT_LEX*
build_show_global_variables(const POS & pos,THD * thd,const String * wild,Item * where_cond)344 build_show_global_variables(const POS &pos, THD *thd, const String *wild, Item *where_cond)
345 {
346 static const LEX_STRING table_name= { C_STRING_WITH_LEN("global_variables")};
347
348 return build_query(pos, thd, SQLCOM_SHOW_VARIABLES, table_name, wild, where_cond);
349 }
350
351