1/*
2   Copyright (c) 2015, 2021, Oracle and/or its affiliates.
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2.0,
6   as published by the Free Software Foundation.
7
8   This program is also distributed with certain software (including
9   but not limited to OpenSSL) that is licensed under separate terms,
10   as designated in a particular file or component or in included license
11   documentation.  The authors of MySQL hereby grant you an additional
12   permission to link the program and your derivative works with the
13   separately licensed software that they have included with MySQL.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License, version 2.0, for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
23
24/*
25  Optimizer hint parser grammar
26*/
27
28%{
29#include "sql_class.h"
30#include "parse_tree_hints.h"
31#include "sql_lex_hints.h"
32#include "sql_const.h"
33
34#define NEW_PTN new (thd->mem_root)
35%}
36
37%pure-parser
38%yacc
39
40%parse-param { class THD *thd }
41%parse-param { class Hint_scanner *scanner }
42%parse-param { class PT_hint_list **ret }
43
44%lex-param { class Hint_scanner *scanner }
45
46%expect 0
47
48
49/* Hint keyword tokens */
50
51%token MAX_EXECUTION_TIME_HINT
52
53%token BKA_HINT
54%token BNL_HINT
55%token DUPSWEEDOUT_HINT
56%token FIRSTMATCH_HINT
57%token INTOEXISTS_HINT
58%token LOOSESCAN_HINT
59%token MATERIALIZATION_HINT
60%token NO_BKA_HINT
61%token NO_BNL_HINT
62%token NO_ICP_HINT
63%token NO_MRR_HINT
64%token NO_RANGE_OPTIMIZATION_HINT
65%token NO_SEMIJOIN_HINT
66%token MRR_HINT
67%token QB_NAME_HINT
68%token SEMIJOIN_HINT
69%token SUBQUERY_HINT
70
71/* Other tokens */
72
73%token HINT_ARG_NUMBER
74%token HINT_ARG_IDENT
75%token HINT_ARG_QB_NAME
76
77%token HINT_CLOSE
78%token HINT_ERROR
79
80/* Types */
81%type <hint_type>
82  key_level_hint_type_on
83  key_level_hint_type_off
84  table_level_hint_type_on
85  table_level_hint_type_off
86
87%type <hint>
88  hint
89  max_execution_time_hint
90  index_level_hint
91  table_level_hint
92  qb_level_hint
93  qb_name_hint
94
95%type <hint_list> hint_list
96
97%type <hint_string> hint_param_index
98
99%type <hint_param_index_list> hint_param_index_list opt_hint_param_index_list
100
101%type <hint_param_table>
102  hint_param_table
103  hint_param_table_ext
104  hint_param_table_empty_qb
105
106%type <hint_param_table_list>
107  hint_param_table_list
108  opt_hint_param_table_list
109  hint_param_table_list_empty_qb
110  opt_hint_param_table_list_empty_qb
111
112%type <hint_string>
113  HINT_ARG_IDENT
114  HINT_ARG_NUMBER
115  HINT_ARG_QB_NAME
116  opt_qb_name
117
118%type <ulong_num>
119  semijoin_strategy semijoin_strategies
120  subquery_strategy
121%%
122
123
124start:
125          hint_list HINT_CLOSE
126          { *ret= $1; }
127        | hint_list error HINT_CLOSE
128          { *ret= $1; }
129        | error HINT_CLOSE
130          { *ret= NULL; }
131        ;
132
133hint_list:
134          hint
135          {
136            $$= NEW_PTN PT_hint_list(thd->mem_root);
137            if ($$ == NULL || $$->push_back($1))
138              YYABORT; // OOM
139          }
140        | hint_list hint
141          {
142            $1->push_back($2);
143            $$= $1;
144          }
145        ;
146
147hint:
148          index_level_hint
149        | table_level_hint
150        | qb_level_hint
151        | qb_name_hint
152        | max_execution_time_hint
153        ;
154
155
156max_execution_time_hint:
157          MAX_EXECUTION_TIME_HINT '(' HINT_ARG_NUMBER ')'
158          {
159            int error;
160            char *end= const_cast<char *>($3.str + $3.length);
161            longlong n= my_strtoll10($3.str, &end, &error);
162            if (error != 0 || end != $3.str + $3.length || n > UINT_MAX32)
163            {
164              scanner->syntax_warning(ER_THD(thd,
165                                             ER_WARN_BAD_MAX_EXECUTION_TIME));
166              $$= NULL;
167            }
168            else
169            {
170              $$= NEW_PTN PT_hint_max_execution_time(n);
171              if ($$ == NULL)
172                YYABORT; // OOM
173            }
174          }
175        ;
176
177
178opt_hint_param_table_list:
179          /* empty */ { $$.init(thd->mem_root); }
180        | hint_param_table_list
181        ;
182
183hint_param_table_list:
184          hint_param_table
185          {
186            $$.init(thd->mem_root);
187            if ($$.push_back($1))
188              YYABORT; // OOM
189          }
190        | hint_param_table_list ',' hint_param_table
191          {
192            if ($1.push_back($3))
193              YYABORT; // OOM
194            $$= $1;
195          }
196        ;
197
198opt_hint_param_table_list_empty_qb:
199          /* empty */ { $$.init(thd->mem_root); }
200        | hint_param_table_list_empty_qb
201        ;
202
203hint_param_table_list_empty_qb:
204          hint_param_table_empty_qb
205          {
206            $$.init(thd->mem_root);
207            if ($$.push_back($1))
208              YYABORT; // OOM
209          }
210        | hint_param_table_list_empty_qb ',' hint_param_table_empty_qb
211          {
212            if ($1.push_back($3))
213              YYABORT; // OOM
214            $$= $1;
215          }
216        ;
217
218opt_hint_param_index_list:
219          /* empty */ { $$.init(thd->mem_root); }
220        | hint_param_index_list
221        ;
222
223hint_param_index_list:
224          hint_param_index
225          {
226            $$.init(thd->mem_root);
227            if ($$.push_back($1))
228              YYABORT; // OOM
229          }
230        | hint_param_index_list ',' hint_param_index
231          {
232            if ($1.push_back($3))
233              YYABORT; // OOM
234            $$= $1;
235          }
236        ;
237
238hint_param_index:
239          HINT_ARG_IDENT
240        ;
241
242hint_param_table_empty_qb:
243          HINT_ARG_IDENT
244          {
245            $$.table= $1;
246            $$.opt_query_block= NULL_CSTR;
247          }
248        ;
249
250hint_param_table:
251          HINT_ARG_IDENT opt_qb_name
252          {
253            $$.table= $1;
254            $$.opt_query_block= $2;
255          }
256        ;
257
258hint_param_table_ext:
259          hint_param_table
260        | HINT_ARG_QB_NAME HINT_ARG_IDENT
261          {
262            $$.table= $2;
263            $$.opt_query_block= $1;
264          }
265        ;
266
267opt_qb_name:
268          /* empty */ { $$= NULL_CSTR; }
269        | HINT_ARG_QB_NAME
270        ;
271
272qb_level_hint:
273          SEMIJOIN_HINT '(' opt_qb_name semijoin_strategies ')'
274          {
275            $$= NEW_PTN PT_qb_level_hint($3, TRUE, SEMIJOIN_HINT_ENUM, $4);
276            if ($$ == NULL)
277              YYABORT; // OOM
278          }
279          |
280          NO_SEMIJOIN_HINT '(' opt_qb_name semijoin_strategies ')'
281          {
282            $$= NEW_PTN PT_qb_level_hint($3, FALSE, SEMIJOIN_HINT_ENUM, $4);
283            if ($$ == NULL)
284              YYABORT; // OOM
285          }
286          |
287          SUBQUERY_HINT '(' opt_qb_name subquery_strategy ')'
288          {
289            $$= NEW_PTN PT_qb_level_hint($3, TRUE, SUBQUERY_HINT_ENUM, $4);
290            if ($$ == NULL)
291              YYABORT; // OOM
292          }
293          ;
294
295semijoin_strategies:
296          /* empty */ { $$= 0; }
297	| semijoin_strategy
298          {
299            $$= $1;
300          }
301        | semijoin_strategies ',' semijoin_strategy
302          {
303            $$= $1 | $3;
304          }
305        ;
306
307semijoin_strategy:
308          FIRSTMATCH_HINT      { $$= OPTIMIZER_SWITCH_FIRSTMATCH; }
309        | LOOSESCAN_HINT       { $$= OPTIMIZER_SWITCH_LOOSE_SCAN; }
310        | MATERIALIZATION_HINT { $$= OPTIMIZER_SWITCH_MATERIALIZATION; }
311        | DUPSWEEDOUT_HINT     { $$= OPTIMIZER_SWITCH_DUPSWEEDOUT; }
312        ;
313
314subquery_strategy:
315          MATERIALIZATION_HINT { $$=
316                                   Item_exists_subselect::EXEC_MATERIALIZATION; }
317        | INTOEXISTS_HINT      { $$= Item_exists_subselect::EXEC_EXISTS; }
318        ;
319
320
321table_level_hint:
322          table_level_hint_type_on '(' opt_hint_param_table_list ')'
323          {
324            $$= NEW_PTN PT_table_level_hint(NULL_CSTR, $3, TRUE, $1);
325            if ($$ == NULL)
326              YYABORT; // OOM
327          }
328        | table_level_hint_type_on
329          '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
330          {
331            $$= NEW_PTN PT_table_level_hint($3, $4, TRUE, $1);
332            if ($$ == NULL)
333              YYABORT; // OOM
334          }
335        | table_level_hint_type_off '(' opt_hint_param_table_list ')'
336          {
337            $$= NEW_PTN PT_table_level_hint(NULL_CSTR, $3, FALSE, $1);
338            if ($$ == NULL)
339              YYABORT; // OOM
340          }
341        | table_level_hint_type_off
342          '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
343          {
344            $$= NEW_PTN PT_table_level_hint($3, $4, FALSE, $1);
345            if ($$ == NULL)
346              YYABORT; // OOM
347          }
348        ;
349
350index_level_hint:
351          key_level_hint_type_on
352          '(' hint_param_table_ext opt_hint_param_index_list ')'
353          {
354            $$= NEW_PTN PT_key_level_hint($3, $4, TRUE, $1);
355            if ($$ == NULL)
356              YYABORT; // OOM
357          }
358        | key_level_hint_type_off
359          '(' hint_param_table_ext opt_hint_param_index_list ')'
360          {
361            $$= NEW_PTN PT_key_level_hint($3, $4, FALSE, $1);
362            if ($$ == NULL)
363              YYABORT; // OOM
364          }
365        ;
366
367table_level_hint_type_on:
368          BKA_HINT
369          {
370            $$= BKA_HINT_ENUM;
371          }
372        | BNL_HINT
373          {
374            $$= BNL_HINT_ENUM;
375          }
376        ;
377
378table_level_hint_type_off:
379          NO_BKA_HINT
380          {
381            $$= BKA_HINT_ENUM;
382          }
383        | NO_BNL_HINT
384          {
385            $$= BNL_HINT_ENUM;
386          }
387        ;
388
389key_level_hint_type_on:
390          MRR_HINT
391          {
392            $$= MRR_HINT_ENUM;
393          }
394        | NO_RANGE_OPTIMIZATION_HINT
395          {
396            $$= NO_RANGE_HINT_ENUM;
397          }
398        ;
399
400key_level_hint_type_off:
401          NO_ICP_HINT
402          {
403            $$= ICP_HINT_ENUM;
404          }
405        | NO_MRR_HINT
406          {
407            $$= MRR_HINT_ENUM;
408          }
409        ;
410
411qb_name_hint:
412          QB_NAME_HINT '(' HINT_ARG_IDENT ')'
413          {
414            $$= NEW_PTN PT_hint_qb_name($3);
415            if ($$ == NULL)
416              YYABORT; // OOM
417          }
418        ;
419