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