diff --git a/mysql-test/r/opt_hints.result b/mysql-test/r/opt_hints.result index da54c85b9c9..8f1368e59b0 100644 --- a/mysql-test/r/opt_hints.result +++ b/mysql-test/r/opt_hints.result @@ -495,7 +495,7 @@ Warnings: Warning 1064 Optimizer hint syntax error near 't3@qb1) */ f2 FROM (SELECT /*+ QB_NAME(qb1) */ f2, f3, f1 FROM t3 WHERE f1 > 2 A' at line 1 Note 1003 /* select#1 */ select `test`.`t3`.`f2` AS `f2` from `test`.`t3` where ((`test`.`t3`.`f3` = 'poiu') and (`test`.`t3`.`f1` > 2) and (`test`.`t3`.`f1` > 2)) -# Check illegal syntax +# Bug #116084 Uniform syntax of join order and table hints EXPLAIN SELECT * FROM (SELECT /*+ QB_NAME(qb1) BKA(@qb1 t1@qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra @@ -503,8 +503,15 @@ id select_type table partitions type possible_keys key key_len ref rows filtered 1 SIMPLE t2 NULL ALL NULL NULL NULL NULL 28 100.00 Using join buffer (hash join) 1 SIMPLE t3 NULL index NULL f2_idx 4 NULL 56 100.00 Using index; Using join buffer (hash join) Warnings: -Warning 1064 Optimizer hint syntax error near 'qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt' at line 2 -Note 1003 /* select#1 */ select `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` join `test`.`t3` +Note 1003 /* select#1 */ select /*+ BKA(`t1`@`qb1`) BKA(`t2`@`qb1`) BKA(`t3`@`qb1`) */ `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` join `test`.`t3` +EXPLAIN SELECT * FROM +(SELECT /*+ QB_NAME(qb1) NO_BKA(@qb1 t1@qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 3 100.00 NULL +1 SIMPLE t2 NULL ALL NULL NULL NULL NULL 28 100.00 Using join buffer (hash join) +1 SIMPLE t3 NULL index NULL f2_idx 4 NULL 56 100.00 Using index; Using join buffer (hash join) +Warnings: +Note 1003 /* select#1 */ select /*+ NO_BKA(`t1`@`qb1`) NO_BKA(`t2`@`qb1`) NO_BKA(`t3`@`qb1`) */ `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` join `test`.`t3` # Check '@qb_name table_name' syntax. BKA should be used for t2. EXPLAIN SELECT /*+ BKA(@qb1 t2) */ * FROM (SELECT /*+ QB_NAME(QB1) */ t2.f1, t2.f2, t2.f3 FROM t1,t2 WHERE t1.f1=t2.f1 AND t2.f2 BETWEEN t1.f1 and t1.f2 and t2.f2 + 1 >= t1.f1 + 1) AS s1; diff --git a/mysql-test/r/opt_hints_join_order.result b/mysql-test/r/opt_hints_join_order.result index 4e614d6e82b..e38069439ed 100644 --- a/mysql-test/r/opt_hints_join_order.result +++ b/mysql-test/r/opt_hints_join_order.result @@ -1128,4 +1128,41 @@ id select_type table partitions type possible_keys key key_len ref rows filtered 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 1 100.00 Using join buffer (hash join) Warnings: Note 1003 /* select#1 */ select /*+ JOIN_PREFIX(@`select#1` `t2`@`qb2`,`t4`@`qb1`,`ta3`,`ta4`) */ count(0) AS `COUNT(*)` from `test`.`t1` join `test`.`t2` `ta3` join `test`.`t2` `ta4` semi join (`test`.`t4`) semi join (`test`.`t2`) where ((`test`.`ta3`.`f2` = `test`.`t2`.`f2`) and (`test`.`ta4`.`f1` = `test`.`t4`.`f1`)) +# Bug #116084 Uniform syntax of join order and table hints +EXPLAIN SELECT /*+ QB_NAME(qb) JOIN_PREFIX(@qb t2@qb2, t4@qb1, ta3, ta4) */ +COUNT(*) FROM t1 JOIN t2 AS ta3 JOIN t2 AS ta4 +WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND +ta3.f2 IN (SELECT /*+ QB_NAME(qb2) */ f2 FROM t2); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL index f2 f2 5 NULL 3 100.00 Using where; Using index; Start temporary +1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (hash join) +1 SIMPLE ta3 NULL ref f2 f2 5 test.t2.f2 1 100.00 Using index +1 SIMPLE ta4 NULL eq_ref PRIMARY PRIMARY 4 test.t4.f1 1 100.00 Using index; End temporary +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 1 100.00 Using join buffer (hash join) +Warnings: +Note 1003 /* select#1 */ select /*+ QB_NAME(`qb`) JOIN_PREFIX(@`qb` `t2`@`qb2`,`t4`@`qb1`,`ta3`,`ta4`) */ count(0) AS `COUNT(*)` from `test`.`t1` join `test`.`t2` `ta3` join `test`.`t2` `ta4` semi join (`test`.`t4`) semi join (`test`.`t2`) where ((`test`.`ta3`.`f2` = `test`.`t2`.`f2`) and (`test`.`ta4`.`f1` = `test`.`t4`.`f1`)) +EXPLAIN SELECT /*+ QB_NAME(qb) JOIN_SUFFIX(@qb t2@qb2, t4@qb1, ta3, ta4) */ +COUNT(*) FROM t1 JOIN t2 AS ta3 JOIN t2 AS ta4 +WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND +ta3.f2 IN (SELECT /*+ QB_NAME(qb2) */ f2 FROM t2); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 1 100.00 Start temporary +1 SIMPLE t2 NULL index f2 f2 5 NULL 3 100.00 Using where; Using index; Using join buffer (hash join) +1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (hash join) +1 SIMPLE ta3 NULL ref f2 f2 5 test.t2.f2 1 100.00 Using index +1 SIMPLE ta4 NULL eq_ref PRIMARY PRIMARY 4 test.t4.f1 1 100.00 Using index; End temporary +Warnings: +Note 1003 /* select#1 */ select /*+ QB_NAME(`qb`) JOIN_SUFFIX(@`qb` `t2`@`qb2`,`t4`@`qb1`,`ta3`,`ta4`) */ count(0) AS `COUNT(*)` from `test`.`t1` join `test`.`t2` `ta3` join `test`.`t2` `ta4` semi join (`test`.`t4`) semi join (`test`.`t2`) where ((`test`.`ta3`.`f2` = `test`.`t2`.`f2`) and (`test`.`ta4`.`f1` = `test`.`t4`.`f1`)) +EXPLAIN SELECT /*+ QB_NAME(qb) JOIN_ORDER(@qb t2@qb2, t4@qb1, ta3, ta4) */ +COUNT(*) FROM t1 JOIN t2 AS ta3 JOIN t2 AS ta4 +WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND +ta3.f2 IN (SELECT /*+ QB_NAME(qb2) */ f2 FROM t2); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 1 100.00 Start temporary +1 SIMPLE t2 NULL index f2 f2 5 NULL 3 100.00 Using where; Using index; Using join buffer (hash join) +1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (hash join) +1 SIMPLE ta3 NULL ref f2 f2 5 test.t2.f2 1 100.00 Using index +1 SIMPLE ta4 NULL eq_ref PRIMARY PRIMARY 4 test.t4.f1 1 100.00 Using index; End temporary +Warnings: +Note 1003 /* select#1 */ select /*+ QB_NAME(`qb`) JOIN_ORDER(@`qb` `t2`@`qb2`,`t4`@`qb1`,`ta3`,`ta4`) */ count(0) AS `COUNT(*)` from `test`.`t1` join `test`.`t2` `ta3` join `test`.`t2` `ta4` semi join (`test`.`t4`) semi join (`test`.`t2`) where ((`test`.`ta3`.`f2` = `test`.`t2`.`f2`) and (`test`.`ta4`.`f1` = `test`.`t4`.`f1`)) DROP TABLE t1, t2, t4; diff --git a/mysql-test/t/opt_hints.test b/mysql-test/t/opt_hints.test index 17932612daa..c8727005522 100644 --- a/mysql-test/t/opt_hints.test +++ b/mysql-test/t/opt_hints.test @@ -259,9 +259,11 @@ EXPLAIN SELECT /*+ BKA(qb1 t3@qb1) */ f2 FROM (SELECT /*+ QB_NAME(qb1) */ f2, f3, f1 FROM t3 WHERE f1 > 2 AND f3 = 'poiu') AS TD WHERE TD.f1 > 2 AND TD.f3 = 'poiu'; ---echo # Check illegal syntax +--echo # Bug #116084 Uniform syntax of join order and table hints EXPLAIN SELECT * FROM (SELECT /*+ QB_NAME(qb1) BKA(@qb1 t1@qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt; +EXPLAIN SELECT * FROM + (SELECT /*+ QB_NAME(qb1) NO_BKA(@qb1 t1@qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt; --echo # Check '@qb_name table_name' syntax. BKA should be used for t2. EXPLAIN SELECT /*+ BKA(@qb1 t2) */ * FROM (SELECT /*+ QB_NAME(QB1) */ t2.f1, t2.f2, t2.f3 FROM t1,t2 diff --git a/mysql-test/t/opt_hints_join_order.test b/mysql-test/t/opt_hints_join_order.test index 3cd6490e273..7ce52951bed 100644 --- a/mysql-test/t/opt_hints_join_order.test +++ b/mysql-test/t/opt_hints_join_order.test @@ -685,5 +685,28 @@ WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND eval $query; eval EXPLAIN $query; +--echo # Bug #116084 Uniform syntax of join order and table hints + +let $query= +SELECT /*+ QB_NAME(qb) JOIN_PREFIX(@qb t2@qb2, t4@qb1, ta3, ta4) */ +COUNT(*) FROM t1 JOIN t2 AS ta3 JOIN t2 AS ta4 +WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND + ta3.f2 IN (SELECT /*+ QB_NAME(qb2) */ f2 FROM t2); +eval EXPLAIN $query; + +let $query= +SELECT /*+ QB_NAME(qb) JOIN_SUFFIX(@qb t2@qb2, t4@qb1, ta3, ta4) */ +COUNT(*) FROM t1 JOIN t2 AS ta3 JOIN t2 AS ta4 +WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND + ta3.f2 IN (SELECT /*+ QB_NAME(qb2) */ f2 FROM t2); +eval EXPLAIN $query; + +let $query= +SELECT /*+ QB_NAME(qb) JOIN_ORDER(@qb t2@qb2, t4@qb1, ta3, ta4) */ +COUNT(*) FROM t1 JOIN t2 AS ta3 JOIN t2 AS ta4 +WHERE ta4.f1 IN (SELECT /*+ QB_NAME(qb1) */ f1 FROM t4) AND + ta3.f2 IN (SELECT /*+ QB_NAME(qb2) */ f2 FROM t2); +eval EXPLAIN $query; + --source include/enable_warnings_if_pq.inc DROP TABLE t1, t2, t4; diff --git a/sql/sql_hints.yy b/sql/sql_hints.yy index f10351b147e..f40ef421f65 100644 --- a/sql/sql_hints.yy +++ b/sql/sql_hints.yy @@ -196,8 +196,6 @@ static bool parse_int(longlong *to, const char *from, size_t from_length) %type hint_param_table_list opt_hint_param_table_list - hint_param_table_list_empty_qb - opt_hint_param_table_list_empty_qb %type HINT_ARG_IDENT @@ -383,26 +381,6 @@ hint_param_table_list: } ; -opt_hint_param_table_list_empty_qb: - /* empty */ { $$.init(thd->mem_root); } - | hint_param_table_list_empty_qb - ; - -hint_param_table_list_empty_qb: - hint_param_table_empty_qb - { - $$.init(thd->mem_root); - if ($$.push_back($1)) - YYABORT; // OOM - } - | hint_param_table_list_empty_qb ',' hint_param_table_empty_qb - { - if ($1.push_back($3)) - YYABORT; // OOM - $$= $1; - } - ; - opt_hint_param_index_list: /* empty */ { $$.init(thd->mem_root); } | hint_param_index_list @@ -486,7 +464,7 @@ qb_level_hint: YYABORT; // OOM } | - JOIN_PREFIX_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')' + JOIN_PREFIX_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list ')' { $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_PREFIX_HINT_ENUM, $4); if ($$ == NULL) @@ -500,7 +478,7 @@ qb_level_hint: YYABORT; // OOM } | - JOIN_SUFFIX_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')' + JOIN_SUFFIX_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list ')' { $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_SUFFIX_HINT_ENUM, $4); if ($$ == NULL) @@ -514,7 +492,7 @@ qb_level_hint: YYABORT; // OOM } | - JOIN_ORDER_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')' + JOIN_ORDER_HINT '(' HINT_ARG_QB_NAME opt_hint_param_table_list ')' { $$= NEW_PTN PT_qb_level_hint($3, true, JOIN_ORDER_HINT_ENUM, $4); if ($$ == NULL) @@ -576,7 +554,7 @@ table_level_hint: YYABORT; // OOM } | table_level_hint_type_on - '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')' + '(' HINT_ARG_QB_NAME opt_hint_param_table_list ')' { $$= NEW_PTN PT_table_level_hint($3, $4, true, $1); if ($$ == NULL) @@ -589,7 +567,7 @@ table_level_hint: YYABORT; // OOM } | table_level_hint_type_off - '(' HINT_ARG_QB_NAME opt_hint_param_table_list_empty_qb ')' + '(' HINT_ARG_QB_NAME opt_hint_param_table_list ')' { $$= NEW_PTN PT_table_level_hint($3, $4, false, $1); if ($$ == NULL)