1/*
2   Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
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 "my_inttypes.h"
30#include "sql/derror.h"
31#include "sql/item_subselect.h"
32#include "sql/parse_tree_helpers.h"  // check_resource_group_name_len
33#include "sql/parse_tree_hints.h"
34#include "sql/parser_yystype.h"
35#include "sql/sql_class.h"
36#include "sql/sql_const.h"
37#include "sql/sql_lex_hints.h"
38
39#define NEW_PTN new (thd->mem_root)
40
41static bool parse_int(longlong *to, const char *from, size_t from_length)
42{
43  int error;
44  const char *end= from + from_length;
45  *to= my_strtoll10(from, &end, &error);
46  return error != 0 || end != from + from_length;
47}
48
49%}
50
51%pure-parser
52
53%parse-param { class THD *thd }
54%parse-param { class Hint_scanner *scanner }
55%parse-param { class PT_hint_list **ret }
56
57%lex-param { class Hint_scanner *scanner }
58
59%expect 0
60
61
62/* Hint keyword tokens */
63
64%token MAX_EXECUTION_TIME_HINT 1000
65%token RESOURCE_GROUP_HINT 1001
66
67%token BKA_HINT 1002
68%token BNL_HINT 1003
69%token DUPSWEEDOUT_HINT 1004
70%token FIRSTMATCH_HINT 1005
71%token INTOEXISTS_HINT 1006
72%token LOOSESCAN_HINT 1007
73%token MATERIALIZATION_HINT 1008
74%token NO_BKA_HINT 1009
75%token NO_BNL_HINT 1010
76%token NO_ICP_HINT 1011
77%token NO_MRR_HINT 1012
78%token NO_RANGE_OPTIMIZATION_HINT 1013
79%token NO_SEMIJOIN_HINT 1014
80%token MRR_HINT 1015
81%token QB_NAME_HINT 1016
82%token SEMIJOIN_HINT 1017
83%token SUBQUERY_HINT 1018
84%token DERIVED_MERGE_HINT 1019
85%token NO_DERIVED_MERGE_HINT 1020
86%token JOIN_PREFIX_HINT 1021
87%token JOIN_SUFFIX_HINT 1022
88%token JOIN_ORDER_HINT 1023
89%token JOIN_FIXED_ORDER_HINT 1024
90%token INDEX_MERGE_HINT 1025
91%token NO_INDEX_MERGE_HINT 1026
92%token SET_VAR_HINT 1027
93%token SKIP_SCAN_HINT 1028
94%token NO_SKIP_SCAN_HINT 1029
95%token HASH_JOIN_HINT 1030
96%token NO_HASH_JOIN_HINT 1031
97
98/* Other tokens */
99
100%token HINT_ARG_NUMBER 1032
101%token HINT_ARG_IDENT 1033
102%token HINT_ARG_QB_NAME 1034
103%token HINT_ARG_TEXT 1035
104%token HINT_IDENT_OR_NUMBER_WITH_SCALE 1036
105
106%token HINT_CLOSE 1037
107%token HINT_ERROR 1038
108
109%token INDEX_HINT 1039
110%token NO_INDEX_HINT 1040
111%token JOIN_INDEX_HINT 1041
112%token NO_JOIN_INDEX_HINT 1042
113%token GROUP_INDEX_HINT 1043
114%token NO_GROUP_INDEX_HINT 1044
115%token ORDER_INDEX_HINT 1045
116%token NO_ORDER_INDEX_HINT 1046
117
118/*
119  YYUNDEF in internal to Bison. Please don't change its number, or change
120  it in sync with YYUNDEF in sql_yacc.yy.
121*/
122%token YYUNDEF 1150
123
124/*
125  Please add new tokens right above this line.
126
127  To make DIGESTS stable, it is desirable to avoid changing token number values.
128*/
129
130/* Types */
131%type <hint_type>
132  key_level_hint_type_on
133  key_level_hint_type_off
134  table_level_hint_type_on
135  table_level_hint_type_off
136
137%type <hint>
138  hint
139  max_execution_time_hint
140  index_level_hint
141  table_level_hint
142  qb_level_hint
143  qb_name_hint
144  set_var_hint
145  resource_group_hint
146
147%type <hint_list> hint_list
148
149%type <lexer.hint_string> hint_param_index
150
151%type <hint_param_index_list> hint_param_index_list opt_hint_param_index_list
152
153%type <hint_param_table>
154  hint_param_table
155  hint_param_table_ext
156  hint_param_table_empty_qb
157
158%type <hint_param_table_list>
159  hint_param_table_list
160  opt_hint_param_table_list
161  hint_param_table_list_empty_qb
162  opt_hint_param_table_list_empty_qb
163
164%type <lexer.hint_string>
165  HINT_ARG_IDENT
166  HINT_ARG_NUMBER
167  HINT_ARG_QB_NAME
168  HINT_ARG_TEXT
169  HINT_IDENT_OR_NUMBER_WITH_SCALE
170  MAX_EXECUTION_TIME_HINT
171  opt_qb_name
172  set_var_ident
173  set_var_text_value
174
175%type <item>
176  set_var_num_item
177  set_var_string_item
178  set_var_arg
179
180%type <ulong_num>
181  semijoin_strategy semijoin_strategies
182  subquery_strategy
183
184%%
185
186
187start:
188          hint_list HINT_CLOSE
189          { *ret= $1; }
190        | hint_list error HINT_CLOSE
191          { *ret= $1; }
192        | error HINT_CLOSE
193          { *ret= NULL; }
194        ;
195
196hint_list:
197          hint
198          {
199            $$= NEW_PTN PT_hint_list(thd->mem_root);
200            if ($$ == NULL || $$->push_back($1))
201              YYABORT; // OOM
202          }
203        | hint_list hint
204          {
205            $1->push_back($2);
206            $$= $1;
207          }
208        ;
209
210hint:
211          index_level_hint
212        | table_level_hint
213        | qb_level_hint
214        | qb_name_hint
215        | max_execution_time_hint
216        | set_var_hint
217        | resource_group_hint
218        ;
219
220
221max_execution_time_hint:
222          MAX_EXECUTION_TIME_HINT '(' HINT_ARG_NUMBER ')'
223          {
224            longlong n;
225            if (parse_int(&n, $3.str, $3.length) || n > UINT_MAX32)
226            {
227              scanner->syntax_warning(ER_THD(thd,
228                                             ER_WARN_BAD_MAX_EXECUTION_TIME));
229              $$= NULL;
230            }
231            else
232            {
233              $$= NEW_PTN PT_hint_max_execution_time(n);
234              if ($$ == NULL)
235                YYABORT; // OOM
236            }
237          }
238        ;
239
240
241opt_hint_param_table_list:
242          /* empty */ { $$.init(thd->mem_root); }
243        | hint_param_table_list
244        ;
245
246hint_param_table_list:
247          hint_param_table
248          {
249            $$.init(thd->mem_root);
250            if ($$.push_back($1))
251              YYABORT; // OOM
252          }
253        | hint_param_table_list ',' hint_param_table
254          {
255            if ($1.push_back($3))
256              YYABORT; // OOM
257            $$= $1;
258          }
259        ;
260
261opt_hint_param_table_list_empty_qb:
262          /* empty */ { $$.init(thd->mem_root); }
263        | hint_param_table_list_empty_qb
264        ;
265
266hint_param_table_list_empty_qb:
267          hint_param_table_empty_qb
268          {
269            $$.init(thd->mem_root);
270            if ($$.push_back($1))
271              YYABORT; // OOM
272          }
273        | hint_param_table_list_empty_qb ',' hint_param_table_empty_qb
274          {
275            if ($1.push_back($3))
276              YYABORT; // OOM
277            $$= $1;
278          }
279        ;
280
281opt_hint_param_index_list:
282          /* empty */ { $$.init(thd->mem_root); }
283        | hint_param_index_list
284        ;
285
286hint_param_index_list:
287          hint_param_index
288          {
289            $$.init(thd->mem_root);
290            if ($$.push_back($1))
291              YYABORT; // OOM
292          }
293        | hint_param_index_list ',' hint_param_index
294          {
295            if ($1.push_back($3))
296              YYABORT; // OOM
297            $$= $1;
298          }
299        ;
300
301hint_param_index:
302          HINT_ARG_IDENT
303        ;
304
305hint_param_table_empty_qb:
306          HINT_ARG_IDENT
307          {
308            $$.table= $1;
309            $$.opt_query_block= NULL_CSTR;
310          }
311        ;
312
313hint_param_table:
314          HINT_ARG_IDENT opt_qb_name
315          {
316            $$.table= $1;
317            $$.opt_query_block= $2;
318          }
319        ;
320
321hint_param_table_ext:
322          hint_param_table
323        | HINT_ARG_QB_NAME HINT_ARG_IDENT
324          {
325            $$.table= $2;
326            $$.opt_query_block= $1;
327          }
328        ;
329
330opt_qb_name:
331          /* empty */ { $$= NULL_CSTR; }
332        | HINT_ARG_QB_NAME
333        ;
334
335qb_level_hint:
336          SEMIJOIN_HINT '(' opt_qb_name semijoin_strategies ')'
337          {
338            $$= NEW_PTN PT_qb_level_hint($3, true, SEMIJOIN_HINT_ENUM, $4);
339            if ($$ == NULL)
340              YYABORT; // OOM
341          }
342          |
343          NO_SEMIJOIN_HINT '(' opt_qb_name semijoin_strategies ')'
344          {
345            $$= NEW_PTN PT_qb_level_hint($3, false, SEMIJOIN_HINT_ENUM, $4);
346            if ($$ == NULL)
347              YYABORT; // OOM
348          }
349          |
350          SUBQUERY_HINT '(' opt_qb_name subquery_strategy ')'
351          {
352            $$= NEW_PTN PT_qb_level_hint($3, true, SUBQUERY_HINT_ENUM, $4);
353            if ($$ == NULL)
354              YYABORT; // OOM
355          }
356          |
357          JOIN_PREFIX_HINT '(' opt_hint_param_table_list ')'
358          {
359            $$= NEW_PTN PT_qb_level_hint(NULL_CSTR, true, JOIN_PREFIX_HINT_ENUM, $3);
360            if ($$ == NULL)
361              YYABORT; // OOM
362          }
363          |
364          JOIN_PREFIX_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
365          {
366            $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_PREFIX_HINT_ENUM, $4);
367            if ($$ == NULL)
368              YYABORT; // OOM
369          }
370          |
371          JOIN_SUFFIX_HINT '(' opt_hint_param_table_list ')'
372          {
373            $$= NEW_PTN PT_qb_level_hint(NULL_CSTR, true, JOIN_SUFFIX_HINT_ENUM, $3);
374            if ($$ == NULL)
375              YYABORT; // OOM
376          }
377          |
378          JOIN_SUFFIX_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
379          {
380            $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_SUFFIX_HINT_ENUM, $4);
381            if ($$ == NULL)
382              YYABORT; // OOM
383          }
384          |
385          JOIN_ORDER_HINT '(' opt_hint_param_table_list ')'
386          {
387            $$= NEW_PTN PT_qb_level_hint(NULL_CSTR, true, JOIN_ORDER_HINT_ENUM, $3);
388            if ($$ == NULL)
389              YYABORT; // OOM
390          }
391          |
392          JOIN_ORDER_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
393          {
394            $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_ORDER_HINT_ENUM, $4);
395            if ($$ == NULL)
396              YYABORT; // OOM
397          }
398          |
399          JOIN_FIXED_ORDER_HINT '(' opt_qb_name  ')'
400          {
401            $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_FIXED_ORDER_HINT_ENUM, 0);
402            if ($$ == NULL)
403              YYABORT; // OOM
404          }
405          ;
406
407semijoin_strategies:
408          /* empty */ { $$= 0; }
409	| semijoin_strategy
410          {
411            $$= $1;
412          }
413        | semijoin_strategies ',' semijoin_strategy
414          {
415            $$= $1 | $3;
416          }
417        ;
418
419semijoin_strategy:
420          FIRSTMATCH_HINT      { $$= OPTIMIZER_SWITCH_FIRSTMATCH; }
421        | LOOSESCAN_HINT       { $$= OPTIMIZER_SWITCH_LOOSE_SCAN; }
422        | MATERIALIZATION_HINT { $$= OPTIMIZER_SWITCH_MATERIALIZATION; }
423        | DUPSWEEDOUT_HINT     { $$= OPTIMIZER_SWITCH_DUPSWEEDOUT; }
424        ;
425
426subquery_strategy:
427          MATERIALIZATION_HINT { $$=
428                                   static_cast<long>(Subquery_strategy::SUBQ_MATERIALIZATION); }
429        | INTOEXISTS_HINT      { $$= static_cast<long>(Subquery_strategy::SUBQ_EXISTS); }
430        ;
431
432
433table_level_hint:
434          table_level_hint_type_on '(' opt_hint_param_table_list ')'
435          {
436            $$= NEW_PTN PT_table_level_hint(NULL_CSTR, $3, true, $1);
437            if ($$ == NULL)
438              YYABORT; // OOM
439          }
440        | table_level_hint_type_on
441          '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
442          {
443            $$= NEW_PTN PT_table_level_hint($3, $4, true, $1);
444            if ($$ == NULL)
445              YYABORT; // OOM
446          }
447        | table_level_hint_type_off '(' opt_hint_param_table_list ')'
448          {
449            $$= NEW_PTN PT_table_level_hint(NULL_CSTR, $3, false, $1);
450            if ($$ == NULL)
451              YYABORT; // OOM
452          }
453        | table_level_hint_type_off
454          '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')'
455          {
456            $$= NEW_PTN PT_table_level_hint($3, $4, false, $1);
457            if ($$ == NULL)
458              YYABORT; // OOM
459          }
460        ;
461
462index_level_hint:
463          key_level_hint_type_on
464          '(' hint_param_table_ext opt_hint_param_index_list ')'
465          {
466            $$= NEW_PTN PT_key_level_hint($3, $4, true, $1);
467            if ($$ == NULL)
468              YYABORT; // OOM
469          }
470        | key_level_hint_type_off
471          '(' hint_param_table_ext opt_hint_param_index_list ')'
472          {
473            $$= NEW_PTN PT_key_level_hint($3, $4, false, $1);
474            if ($$ == NULL)
475              YYABORT; // OOM
476          }
477        ;
478
479table_level_hint_type_on:
480          BKA_HINT
481          {
482            $$= BKA_HINT_ENUM;
483          }
484        | BNL_HINT
485          {
486            $$= BNL_HINT_ENUM;
487          }
488        | HASH_JOIN_HINT
489          {
490            $$= HASH_JOIN_HINT_ENUM;
491          }
492        | DERIVED_MERGE_HINT
493          {
494            $$= DERIVED_MERGE_HINT_ENUM;
495          }
496        ;
497
498table_level_hint_type_off:
499          NO_BKA_HINT
500          {
501            $$= BKA_HINT_ENUM;
502          }
503        | NO_BNL_HINT
504          {
505            $$= BNL_HINT_ENUM;
506          }
507        | NO_HASH_JOIN_HINT
508          {
509            $$= HASH_JOIN_HINT_ENUM;
510          }
511        | NO_DERIVED_MERGE_HINT
512          {
513            $$= DERIVED_MERGE_HINT_ENUM;
514          }
515        ;
516
517key_level_hint_type_on:
518          MRR_HINT
519          {
520            $$= MRR_HINT_ENUM;
521          }
522        | NO_RANGE_OPTIMIZATION_HINT
523          {
524            $$= NO_RANGE_HINT_ENUM;
525          }
526        | INDEX_MERGE_HINT
527          {
528            $$= INDEX_MERGE_HINT_ENUM;
529          }
530        | SKIP_SCAN_HINT
531          {
532            $$= SKIP_SCAN_HINT_ENUM;
533          }
534        | INDEX_HINT
535          {
536            $$= INDEX_HINT_ENUM;
537          }
538        | JOIN_INDEX_HINT
539          {
540            $$= JOIN_INDEX_HINT_ENUM;
541          }
542        | GROUP_INDEX_HINT
543          {
544            $$= GROUP_INDEX_HINT_ENUM;
545          }
546        | ORDER_INDEX_HINT
547          {
548            $$= ORDER_INDEX_HINT_ENUM;
549          }
550        ;
551
552key_level_hint_type_off:
553          NO_ICP_HINT
554          {
555            $$= ICP_HINT_ENUM;
556          }
557        | NO_MRR_HINT
558          {
559            $$= MRR_HINT_ENUM;
560          }
561        | NO_INDEX_MERGE_HINT
562          {
563            $$= INDEX_MERGE_HINT_ENUM;
564          }
565        | NO_SKIP_SCAN_HINT
566          {
567            $$= SKIP_SCAN_HINT_ENUM;
568          }
569        | NO_INDEX_HINT
570          {
571            $$= INDEX_HINT_ENUM;
572          }
573        | NO_JOIN_INDEX_HINT
574          {
575            $$= JOIN_INDEX_HINT_ENUM;
576          }
577        | NO_GROUP_INDEX_HINT
578          {
579            $$= GROUP_INDEX_HINT_ENUM;
580          }
581        | NO_ORDER_INDEX_HINT
582          {
583            $$= ORDER_INDEX_HINT_ENUM;
584          }
585        ;
586
587qb_name_hint:
588          QB_NAME_HINT '(' HINT_ARG_IDENT ')'
589          {
590            $$= NEW_PTN PT_hint_qb_name($3);
591            if ($$ == NULL)
592              YYABORT; // OOM
593          }
594        ;
595
596set_var_hint:
597          SET_VAR_HINT '(' set_var_ident '=' set_var_arg ')'
598          {
599            $$= NEW_PTN PT_hint_sys_var($3, $5);
600            if ($$ == NULL)
601              YYABORT; // OOM
602          }
603        ;
604
605resource_group_hint:
606         RESOURCE_GROUP_HINT '(' HINT_ARG_IDENT ')'
607         {
608           if (check_resource_group_name_len($3, Sql_condition::SL_WARNING))
609             YYERROR;
610
611           $$= NEW_PTN PT_hint_resource_group($3);
612           if ($$ == nullptr)
613              YYABORT; // OOM
614         }
615       ;
616
617set_var_ident:
618          HINT_ARG_IDENT
619        | MAX_EXECUTION_TIME_HINT
620        ;
621
622set_var_num_item:
623          HINT_ARG_NUMBER
624          {
625            longlong n;
626            if (parse_int(&n, $1.str, $1.length))
627            {
628              scanner->syntax_warning(ER_THD(thd, ER_WRONG_SIZE_NUMBER));
629              $$= NULL;
630            }
631            else
632            {
633              $$= NEW_PTN Item_int((ulonglong)n);
634              if ($$ == NULL)
635                YYABORT; // OOM
636            }
637          }
638        | HINT_IDENT_OR_NUMBER_WITH_SCALE
639          {
640            longlong n;
641            if (parse_int(&n, $1.str, $1.length - 1))
642            {
643              scanner->syntax_warning(ER_THD(thd, ER_WRONG_SIZE_NUMBER));
644              $$= NULL;
645            }
646            else
647            {
648              int multiplier;
649              switch ($1.str[$1.length - 1]) {
650              case 'K': multiplier= 1024; break;
651              case 'M': multiplier= 1024 * 1024; break;
652              case 'G': multiplier= 1024 * 1024 * 1024; break;
653              default:
654                DBUG_ASSERT(0); // should not happen
655                YYABORT;        // for sure
656              }
657              if (1.0L * n * multiplier > LLONG_MAX)
658              {
659                scanner->syntax_warning(ER_THD(thd, ER_WRONG_SIZE_NUMBER));
660                $$= NULL;
661              }
662              else
663              {
664                $$= NEW_PTN Item_int((ulonglong)n * multiplier);
665                if ($$ == NULL)
666                  YYABORT; // OOM
667              }
668            }
669          }
670        ;
671
672set_var_text_value:
673        HINT_ARG_IDENT
674        | HINT_ARG_TEXT
675        ;
676
677set_var_string_item:
678        set_var_text_value
679        {
680          $$= NEW_PTN Item_string($1.str, $1.length, thd->charset());
681          if ($$ == NULL)
682            YYABORT; // OOM
683        }
684
685set_var_arg:
686    set_var_string_item
687    | set_var_num_item
688    ;
689