--- a PPN by Garber Painting Akron. With Image Size Reduction included!URL: http://github.com/MariaDB/server/pull/4692.diff
@@ EXPLAIN EXTENDED INSERT INTO t3(f1, f2, f3)
--echo # Turn off ICP for a particular table and a key
EXPLAIN EXTENDED INSERT INTO t3(f1, f2, f3)
- (SELECT /*+ QB_NAME(qb1) NO_ICP(t5@QB1 x_idx)*/ t4.x, t5.y, 'filler' FROM t4, t4 t5
+ (SELECT /*+ NO_ICP(t5@QB1 x_idx) QB_NAME(qb1) */ t4.x, t5.y, 'filler' FROM t4, t4 t5
WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0);
--echo # Make sure ICP is expected to be used when there are no hints
@@ -308,8 +328,8 @@ EXPLAIN EXTENDED REPLACE INTO t3(f1, f2, f3)
--echo # Should issue warning
EXPLAIN EXTENDED SELECT /*+ QB_NAME(qb1) QB_NAME(qb1 ) */ * FROM t2;
---echo # Should issue warning
-EXPLAIN EXTENDED SELECT /*+ BKA(@qb1) QB_NAME(qb1) */ t2.f1, t2.f2, t2.f3 FROM t1,t2
+--echo # QB_NAME may appear after the hint, but the hint is still resolved
+EXPLAIN EXTENDED SELECT /*+ NO_BNL(@qb1) 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;
--echo # Should not crash
diff --git a/mysql-test/main/opt_hints_impl_qb_name.inc b/mysql-test/main/opt_hints_impl_qb_name.inc
new file mode 100644
index 0000000000000..04b1107468d61
--- /dev/null
+++ b/mysql-test/main/opt_hints_impl_qb_name.inc
@@ -0,0 +1,241 @@
+--source include/have_sequence.inc
+--enable_prepare_warnings
+
+create table t1 (a int, b int, c char(20), key idx_a(a), key idx_ab(a, b));
+
+insert into t1 select seq, seq, 'filler' from seq_1_to_100;
+
+create table t2 as select * from t1;
+
+analyze table t1,t2 persistent for all;
+
+--echo # Table-level hint
+explain extended select /*+ no_bnl(t2@dt)*/ * from
+ (select t1.* from t1, t2 where t1.a > t2.a) as dt;
+
+--echo # More than one reference to a single QB
+explain extended select /*+ no_bnl(t2@dt) no_index(t1@dt)*/ * from
+ (select t1.* from t1, t2 where t1.a > t2.a) as dt;
+
+--echo # QB-level hint
+explain extended select /*+ no_bnl(@dt)*/ * from
+ (select t1.* from t1, t2 where t1.a > t2.a) as dt;
+
+--echo # Index-level hints
+--echo # Without the hint 'range' index access would be chosen
+explain extended select /*+ no_index(t1@`T`)*/ * from
+ (select * from t1 where a < 3) t;
+
+--echo # Without the hint 'range' index access would be chosen
+explain extended select /*+ no_range_optimization(t1@t1)*/ * from
+ (select * from t1 where a > 100 and a < 120) as t1;
+
+--echo # Regular and derived tables share same name but the hint is applied correctly
+explain extended select /*+ index(t1@t1 idx_ab)*/ * from
+ (select * from t1 where a < 3) as t1;
+
+explain extended select /*+ no_index(t1@t2 idx_a) index(t1@t1 idx_ab)*/ * from
+ (select * from t1 where a < 3) as t1, (select * from t1 where a < 5) as t2;
+
+explain extended select /*+ no_index(t1@t1 idx_a, idx_ab)*/ * from
+ (select * from t1 where a < 3) as t1, (select * from t1 where a < 5) as t2;
+
+--echo # Nested derived tables
+explain extended select /*+ no_bnl(t1@dt2)*/ * from
+ (select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+
+explain extended select /*+ no_index(t1@DT2)*/ * from
+ (select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+
+--echo # Explicit QB name overrides the implicit one
+explain extended select /*+ no_index(t1@dt2)*/ * from
+ (select count(*) from t1, (select /*+ qb_name(dt2)*/ * from t1 where a < 5) dt1) as dt2;
+
+--echo # Both hints are applied
+explain extended select /*+ no_index(t1@dt1) no_bnl(t1@dt2)*/ * from
+ (select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+
+--disable_ps_protocol
+# PS protocol is disabled because the warning is genererated only during
+# PREPARE step of a statement. When the QB name cannot be resolved the hint
+# is discarded, so it is not present during EXECUTE step. The same applies
+# not only to implicit but also to explicit QB names.
+
+--echo # Nested derived tables with ambiguous names, hint is ignored
+explain extended select /*+ no_index(t1@t1)*/* from
+ (select count(*) from t1, (select * from t1 where a < 5) t1) as t1;
+
+--echo # The hint cannot be applied to a derived table with UNION
+explain extended select /*+ no_index(t2@t1)*/* from
+ (select * from t1 where a < 3 union select * from t2 where a < 9) as t1;
+
+explain extended select /*+ no_index(t1@t1)*/* from
+ (select * from t1 where a < 3 union select * from t2 where a < 9) as t1;
+
+--echo # Test INSERT..SELECT
+explain extended insert into t2 select /*+ no_bnl(t2@dt)*/ * from
+ (select t1.* from t1, t2 where t1.a > t2.a) as dt;
+
+--echo # Test MERGE and NO_MERGE hints
+explain extended select /*+ merge(@dt)*/ * from
+ (select * from (select t1.* from t1, t2 where t1.a > t2.a) as dt1) as dt;
+
+explain extended select /*+ no_merge(@dt)*/ * from
+ (select * from (select t1.* from t1, t2 where t1.a > t2.a) as dt1) as dt;
+
+--echo # Multiple levels of nested derived tables, all hints are applied
+explain extended
+select /*+ no_merge(dv) no_bnl(t2@dt) */ * from (
+ select /*+ no_merge(du) */ * from (
+ select /*+ no_merge(dt) */ * from (
+ select t1.* from t1, t2 where t1.a > t2.a
+ ) dt
+ ) du
+) dv;
+
+--enable_ps_protocol
+
+--echo # ======================================
+--echo # Test CTEs
+--echo # By default BNL and index access to t1 are used.
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select * from cte;
+
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(t1@cte)*/ * from cte;
+
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(@cte)*/ * from cte;
+
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte)*/ * from cte;
+
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte) no_index(t1@dt1)*/ * from cte;
+
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@dt1 idx_a) no_bnl(@cte)*/ * from cte;
+
+
+--disable_ps_protocol
+# See the comment above for why PS protocol is disabled
+
+--echo # Ambiguity: multiple occurencies of `cte`, the hint is ignored
+explain extended
+with cte as (select count(*) as cnt from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(@cte)*/ * from cte where cnt > 10
+union
+select * from cte where cnt < 100;
+
+--echo # However, if CTE occurencies have different aliases, the hint can be applied
+explain extended
+with cte as (select count(*) as cnt from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte1)*/ * from cte as cte1 where cnt > 10
+union
+select * from cte where cnt < 100;
+
+--enable_ps_protocol
+
+--echo # ======================================
+--echo # Test views
+create view v1 as select * from t1 where a < 100;
+
+--echo # Default execution plan
+explain extended select *
+ from v1, v1 as v2 where v1.a = v2.a and v1.a < 3;
+
+explain extended
+ select /*+ index(t1@v1 idx_ab) no_index(t1@`v2`)*/ *
+ from v1, v1 as v2 where v1.a = v2.a and v1.a < 3;
+
+--echo # Nested views
+create view v2 as select * from v1 where a < 300;
+
+--echo # Default execution plan
+explain extended select * from v2;
+
+--echo # Addressing an object inside a nested view
+explain extended select /*+ index(t1@`v1` idx_ab)*/ * from v2;
+
+create view v3 as select * from t1 union select * from t2;
+
+--disable_ps_protocol
+# See the comment above for why PS protocol is disabled
+
+--echo # Unable to apply the hint to a view with UNION
+explain extended select /*+ no_index(t1@v3) */ * from v3;
+
+--echo # Ambiguity: view `v1` appears two times - should warn and ignore hint
+explain extended select /*+ index(t2@v1) */ * from v1,
+ (select a from v1 where b > 5) dt;
+
+--enable_ps_protocol
+
+--echo # Implicit QB names are not supported inside views
+create view v4 as select /*+ no_bnl(t2@dt)*/ * from
+ (select t1.* from t1, t2 where t1.a > t2.a) as dt;
+
+show create view v4;
+
+--echo # However, a derived table inside a view can be addressed from outer query
+create view v5 as select dt.a from
+ t1, (select t1.* from t1, t2 where t1.a > t2.a) as dt where t1.a=dt.a;
+
+--echo # Addressing a single table
+explain extended select /*+ no_bnl(t2@dt) */* from v5;
+--echo # Addressing the whole derived table
+explain extended select /*+ no_bnl(@dt) */* from v5;
+
+--echo # Derived tables inside views can be addressed by their aliases
+explain extended select /*+ no_bnl(t2@dt) */ * from v4;
+
+drop view v1, v2, v3, v4, v5;
+
+--echo # ======================================
+--echo # Not supported for DML, check presence of warnings
+
+--disable_ps_protocol
+explain extended
+update /*+ no_range_optimization(t1@dt)*/ t2,
+ (select a from t1 where a > 10) dt
+set b=1 where t2.a = dt.a;
+
+explain extended
+delete /*+ no_index(t1@dt)*/ from t2
+where t2.a in
+ (select * from (select a from t1 where a > 10) dt where dt.a > 20);
+
+--echo # ======================================
+--echo # Objects in triggers and stored functions must not be visible for hints
+create table t3 (a int, b int);
+
+--echo # Trigger with derived table inside
+delimiter |;
+create trigger tr1 before insert on t3
+for each row
+begin
+ set new.b = (select max(a) from
+ (select a from t1 where a < new.a) dt);
+end|
+delimiter ;|
+
+--echo # Warning expected
+explain extended select /*+ no_index(t1@dt) */ max(a) from t3 where a<2;
+
+--echo # Stored function with derived table inside
+create function get_max(p_a int) returns int
+return (select max(a) from
+ (select a from t1 where a < p_a) dt);
+
+--echo # Warning expected
+explain extended select /*+ no_index(t1@dt) */ a, get_max(a) from t1;
+
+--enable_ps_protocol
+drop function get_max;
+drop table t1, t2, t3;
\ No newline at end of file
diff --git a/mysql-test/main/opt_hints_impl_qb_name.result b/mysql-test/main/opt_hints_impl_qb_name.result
new file mode 100644
index 0000000000000..3c73eb3c491fa
--- /dev/null
+++ b/mysql-test/main/opt_hints_impl_qb_name.result
@@ -0,0 +1,850 @@
+set optimizer_switch = 'derived_merge=on';
+create table t1 (a int, b int, c char(20), key idx_a(a), key idx_ab(a, b));
+insert into t1 select seq, seq, 'filler' from seq_1_to_100;
+create table t2 as select * from t1;
+analyze table t1,t2 persistent for all;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+# Table-level hint
+explain extended select /*+ no_bnl(t2@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 select /*+ NO_BNL(`t2`@`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`
+# More than one reference to a single QB
+explain extended select /*+ no_bnl(t2@dt) no_index(t1@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 select /*+ NO_BNL(`t2`@`dt`) NO_INDEX(`t1`@`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`
+# QB-level hint
+explain extended select /*+ no_bnl(@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 select /*+ NO_BNL(@`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`
+# Index-level hints
+# Without the hint 'range' index access would be chosen
+explain extended select /*+ no_index(t1@`T`)*/ * from
+(select * from t1 where a < 3) t;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 2.00 Using where
+Warnings:
+Note 1003 select /*+ NO_INDEX(`t1`@`T`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3
+# Without the hint 'range' index access would be chosen
+explain extended select /*+ no_range_optimization(t1@t1)*/ * from
+(select * from t1 where a > 100 and a < 120) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 1.00 Using where
+Warnings:
+Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t1`@`t1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` > 100 and `test`.`t1`.`a` < 120
+# Regular and derived tables share same name but the hint is applied correctly
+explain extended select /*+ index(t1@t1 idx_ab)*/ * from
+(select * from t1 where a < 3) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 select /*+ INDEX(`t1`@`t1` `idx_ab`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3
+explain extended select /*+ no_index(t1@t2 idx_a) index(t1@t1 idx_ab)*/ * from
+(select * from t1 where a < 3) as t1, (select * from t1 where a < 5) as t2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 2 100.00 Using index condition
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 3 100.00 Using index condition; Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select /*+ NO_INDEX(`t1`@`t2` `idx_a`) INDEX(`t1`@`t1` `idx_ab`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5 and `test`.`t1`.`a` < 3
+explain extended select /*+ no_index(t1@t1 idx_a, idx_ab)*/ * from
+(select * from t1 where a < 3) as t1, (select * from t1 where a < 5) as t2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 2.00 Using where
+1 SIMPLE t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition; Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select /*+ NO_INDEX(`t1`@`t1` `idx_a`,`idx_ab`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5 and `test`.`t1`.`a` < 3
+# Nested derived tables
+explain extended select /*+ no_bnl(t1@dt2)*/ * from
+(select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(`t1`@`dt2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select /*+ QB_NAME(`dt2`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5) `dt2`
+explain extended select /*+ no_index(t1@DT2)*/ * from
+(select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`DT2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select /*+ QB_NAME(`DT2`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5) `dt2`
+# Explicit QB name overrides the implicit one
+explain extended select /*+ no_index(t1@dt2)*/ * from
+(select count(*) from t1, (select /*+ qb_name(dt2)*/ * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 400 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 4.00 Using where
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`dt2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5) `dt2`
+# Both hints are applied
+explain extended select /*+ no_index(t1@dt1) no_bnl(t1@dt2)*/ * from
+(select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 400 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 4.00 Using where
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`dt1`) NO_BNL(`t1`@`dt2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select /*+ QB_NAME(`dt2`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5) `dt2`
+# Nested derived tables with ambiguous names, hint is ignored
+explain extended select /*+ no_index(t1@t1)*/* from
+(select count(*) from t1, (select * from t1 where a < 5) t1) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+Warnings:
+Warning 4256 Query block name `t1` is ambiguous for NO_INDEX hint
+Note 1003 /* select#1 */ select `t1`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5) `t1`
+# The hint cannot be applied to a derived table with UNION
+explain extended select /*+ no_index(t2@t1)*/* from
+(select * from t1 where a < 3 union select * from t2 where a < 9) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 9 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 1 100.00 Using index condition
+3 UNION t2 ALL NULL NULL NULL NULL 100 8.00 Using where
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4257 Implicit query block name `t1` is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for NO_INDEX hint
+Note 1003 /* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3 union /* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`a` < 9) `t1`
+explain extended select /*+ no_index(t1@t1)*/* from
+(select * from t1 where a < 3 union select * from t2 where a < 9) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 9 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 1 100.00 Using index condition
+3 UNION t2 ALL NULL NULL NULL NULL 100 8.00 Using where
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4257 Implicit query block name `t1` is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for NO_INDEX hint
+Note 1003 /* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3 union /* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`a` < 9) `t1`
+# Test INSERT..SELECT
+explain extended insert into t2 select /*+ no_bnl(t2@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00 Using temporary
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 insert into `test`.`t2` select /*+ NO_BNL(`t2`@`dt`) */ sql_buffer_result `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`
+# Test MERGE and NO_MERGE hints
+explain extended select /*+ merge(@dt)*/ * from
+(select * from (select t1.* from t1, t2 where t1.a > t2.a) as dt1) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select /*+ MERGE(@`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`
+explain extended select /*+ no_merge(@dt)*/ * from
+(select * from (select t1.* from t1, t2 where t1.a > t2.a) as dt1) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+3 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+3 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_MERGE(@`dt`) */ `dt1`.`a` AS `a`,`dt1`.`b` AS `b`,`dt1`.`c` AS `c` from (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt1`
+# Multiple levels of nested derived tables, all hints are applied
+explain extended
+select /*+ no_merge(dv) no_bnl(t2@dt) */ * from (
+select /*+ no_merge(du) */ * from (
+select /*+ no_merge(dt) */ * from (
+select t1.* from t1, t2 where t1.a > t2.a
+) dt
+) du
+) dv;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED ALL NULL NULL NULL NULL 10000 100.00
+3 DERIVED ALL NULL NULL NULL NULL 10000 100.00
+4 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+4 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_MERGE(`dt`@`select#3`) NO_MERGE(`du`@`select#2`) NO_MERGE(`dv`@`select#1`) NO_BNL(`t2`@`dt`) */ `dv`.`a` AS `a`,`dv`.`b` AS `b`,`dv`.`c` AS `c` from (/* select#2 */ select `du`.`a` AS `a`,`du`.`b` AS `b`,`du`.`c` AS `c` from (/* select#3 */ select `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#4 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`) `du`) `dv`
+# ======================================
+# Test CTEs
+# By default BNL and index access to t1 are used.
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 with cte as (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5)/* select#1 */ select `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(t1@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5)/* select#1 */ select /*+ NO_BNL(`t1`@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5)/* select#1 */ select /*+ NO_BNL(@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5)/* select#1 */ select /*+ NO_INDEX(`t1`@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte) no_index(t1@dt1)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 400 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 4.00 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5)/* select#1 */ select /*+ NO_INDEX(`t1`@`cte`) NO_INDEX(`t1`@`dt1`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@dt1 idx_a) no_bnl(@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 300 100.00
+2 DERIVED t1 range idx_ab idx_ab 5 NULL 3 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5)/* select#1 */ select /*+ NO_INDEX(`t1`@`dt1` `idx_a`) NO_BNL(@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+# Ambiguity: multiple occurencies of `cte`, the hint is ignored
+explain extended
+with cte as (select count(*) as cnt from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(@cte)*/ * from cte where cnt > 10
+union
+select * from cte where cnt < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00 Using where
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+4 UNION ALL NULL NULL NULL NULL 200 100.00 Using where
+5 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+5 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4256 Query block name `cte` is ambiguous for NO_BNL hint
+Note 1003 with cte as (/* select#2 */ select count(0) AS `cnt` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5 having `cnt` > 10)/* select#1 */ select `cte`.`cnt` AS `cnt` from `cte` where `cte`.`cnt` > 10 union /* select#4 */ select `cte`.`cnt` AS `cnt` from `cte` where `cte`.`cnt` < 100
+# However, if CTE occurencies have different aliases, the hint can be applied
+explain extended
+with cte as (select count(*) as cnt from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte1)*/ * from cte as cte1 where cnt > 10
+union
+select * from cte where cnt < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00 Using where
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+4 UNION ALL NULL NULL NULL NULL 200 100.00 Using where
+5 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using where; Using index
+5 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte1`) */ count(0) AS `cnt` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` < 5 having `cnt` > 10)/* select#1 */ select /*+ NO_INDEX(`t1`@`cte1`) */ `cte1`.`cnt` AS `cnt` from `cte` `cte1` where `cte1`.`cnt` > 10 union /* select#4 */ select `cte`.`cnt` AS `cnt` from `cte` where `cte`.`cnt` < 100
+# ======================================
+# Test views
+create view v1 as select * from t1 where a < 100;
+# Default execution plan
+explain extended select *
+from v1, v1 as v2 where v1.a = v2.a and v1.a < 3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_a,idx_ab idx_a 5 NULL 1 100.00 Using index condition
+1 SIMPLE t1 ref idx_a,idx_ab idx_a 5 test.t1.a 1 100.00
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 3 and `test`.`t1`.`a` < 100 and `test`.`t1`.`a` < 100
+explain extended
+select /*+ index(t1@v1 idx_ab) no_index(t1@`v2`)*/ *
+from v1, v1 as v2 where v1.a = v2.a and v1.a < 3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 2 100.00 Using index condition
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 99.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select /*+ INDEX(`t1`@`v1` `idx_ab`) NO_INDEX(`t1`@`v2`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 3 and `test`.`t1`.`a` < 100 and `test`.`t1`.`a` < 100
+# Nested views
+create view v2 as select * from v1 where a < 300;
+# Default execution plan
+explain extended select * from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 94.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 300 and `test`.`t1`.`a` < 100
+# Addressing an object inside a nested view
+explain extended select /*+ index(t1@`v1` idx_ab)*/ * from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 99 100.00 Using index condition
+Warnings:
+Note 1003 select /*+ INDEX(`t1`@`v1` `idx_ab`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 300 and `test`.`t1`.`a` < 100
+create view v3 as select * from t1 union select * from t2;
+# Unable to apply the hint to a view with UNION
+explain extended select /*+ no_index(t1@v3) */ * from v3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00
+3 UNION t2 ALL NULL NULL NULL NULL 100 100.00
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4257 Implicit query block name `v3` is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for NO_INDEX hint
+Note 1003 /* select#1 */ select `v3`.`a` AS `a`,`v3`.`b` AS `b`,`v3`.`c` AS `c` from `test`.`v3`
+# Ambiguity: view `v1` appears two times - should warn and ignore hint
+explain extended select /*+ index(t2@v1) */ * from v1,
+(select a from v1 where b > 5) dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_a,idx_ab idx_ab 5 NULL 99 90.20 Using where; Using index
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 94.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Warning 4256 Query block name `v1` is ambiguous for INDEX hint
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`b` > 5 and `test`.`t1`.`a` < 100 and `test`.`t1`.`a` < 100
+# Implicit QB names are not supported inside views
+create view v4 as select /*+ no_bnl(t2@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+Warnings:
+Warning 4242 Implicit query block names are ignored for hints specified within VIEWs
+show create view v4;
+View Create View character_set_client collation_connection
+v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS select `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (`t1` join `t2`) where `t1`.`a` > `t2`.`a`) `dt` latin1 latin1_swedish_ci
+# However, a derived table inside a view can be addressed from outer query
+create view v5 as select dt.a from
+t1, (select t1.* from t1, t2 where t1.a > t2.a) as dt where t1.a=dt.a;
+# Addressing a single table
+explain extended select /*+ no_bnl(t2@dt) */* from v5;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 index idx_a,idx_ab idx_a 5 NULL 100 100.00 Using where; Using index
+1 SIMPLE t1 ref idx_a,idx_ab idx_a 5 test.t1.a 1 100.00 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 select /*+ NO_BNL(`t2`@`dt`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` > `test`.`t2`.`a`
+# Addressing the whole derived table
+explain extended select /*+ no_bnl(@dt) */* from v5;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 index idx_a,idx_ab idx_a 5 NULL 100 100.00 Using where; Using index
+1 SIMPLE t1 ref idx_a,idx_ab idx_a 5 test.t1.a 1 100.00 Using index
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 select /*+ NO_BNL(@`dt`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` > `test`.`t2`.`a`
+# Derived tables inside views can be addressed by their aliases
+explain extended select /*+ no_bnl(t2@dt) */ * from v4;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 select /*+ NO_BNL(`t2`@`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`
+drop view v1, v2, v3, v4, v5;
+# ======================================
+# Not supported for DML, check presence of warnings
+explain extended
+update /*+ no_range_optimization(t1@dt)*/ t2,
+(select a from t1 where a > 10) dt
+set b=1 where t2.a = dt.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 9 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_ab 5 NULL 92 100.00 Using where; Using index
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_RANGE_OPTIMIZATION hint
+Note 1003 /* select#1 */ update `test`.`t2` join (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 10) `dt` set `test`.`t2`.`b` = 1 where `dt`.`a` = `test`.`t2`.`a`
+explain extended
+delete /*+ no_index(t1@dt)*/ from t2
+where t2.a in
+(select * from (select a from t1 where a > 10) dt where dt.a > 20);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 90.00 Using where
+1 PRIMARY t1 ref idx_a,idx_ab idx_a 5 test.t2.a 1 100.00 Using index; FirstMatch(t2)
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_INDEX hint
+Note 1003 delete from `test`.`t2` using (`test`.`t1`) where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t2`.`a` > 20 and `test`.`t2`.`a` > 10
+# ======================================
+# Objects in triggers and stored functions must not be visible for hints
+create table t3 (a int, b int);
+# Trigger with derived table inside
+create trigger tr1 before insert on t3
+for each row
+begin
+set new.b = (select max(a) from
+(select a from t1 where a < new.a) dt);
+end|
+# Warning expected
+explain extended select /*+ no_index(t1@dt) */ max(a) from t3 where a<2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_INDEX hint
+Note 1003 select max(NULL) AS `max(a)` from `test`.`t3` where 0
+# Stored function with derived table inside
+create function get_max(p_a int) returns int
+return (select max(a) from
+(select a from t1 where a < p_a) dt);
+# Warning expected
+explain extended select /*+ no_index(t1@dt) */ a, get_max(a) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_INDEX hint
+Note 1003 select `test`.`t1`.`a` AS `a`,`get_max`(`test`.`t1`.`a`) AS `get_max(a)` from `test`.`t1`
+drop function get_max;
+drop table t1, t2, t3;
+set optimizer_switch = 'derived_merge=off';
+create table t1 (a int, b int, c char(20), key idx_a(a), key idx_ab(a, b));
+insert into t1 select seq, seq, 'filler' from seq_1_to_100;
+create table t2 as select * from t1;
+analyze table t1,t2 persistent for all;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+# Table-level hint
+explain extended select /*+ no_bnl(t2@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+2 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(`t2`@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`
+# More than one reference to a single QB
+explain extended select /*+ no_bnl(t2@dt) no_index(t1@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00
+2 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(`t2`@`dt`) NO_INDEX(`t1`@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`
+# QB-level hint
+explain extended select /*+ no_bnl(@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+2 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`
+# Index-level hints
+# Without the hint 'range' index access would be chosen
+explain extended select /*+ no_index(t1@`T`)*/ * from
+(select * from t1 where a < 3) t;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 2.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`T`) */ `t`.`a` AS `a`,`t`.`b` AS `b`,`t`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`T`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3) `t`
+# Without the hint 'range' index access would be chosen
+explain extended select /*+ no_range_optimization(t1@t1)*/ * from
+(select * from t1 where a > 100 and a < 120) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 1.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_RANGE_OPTIMIZATION(`t1`@`t1`) */ `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`t1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` > 100 and `test`.`t1`.`a` < 120) `t1`
+# Regular and derived tables share same name but the hint is applied correctly
+explain extended select /*+ index(t1@t1 idx_ab)*/ * from
+(select * from t1 where a < 3) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 range idx_ab idx_ab 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 /* select#1 */ select /*+ INDEX(`t1`@`t1` `idx_ab`) */ `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`t1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3) `t1`
+explain extended select /*+ no_index(t1@t2 idx_a) index(t1@t1 idx_ab)*/ * from
+(select * from t1 where a < 3) as t1, (select * from t1 where a < 5) as t2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_ab idx_ab 5 NULL 3 100.00 Using index condition
+2 DERIVED t1 range idx_ab idx_ab 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`t2` `idx_a`) INDEX(`t1`@`t1` `idx_ab`) */ `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`t1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3) `t1` join (/* select#3 */ select /*+ QB_NAME(`t2`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `t2`
+explain extended select /*+ no_index(t1@t1 idx_a, idx_ab)*/ * from
+(select * from t1 where a < 3) as t1, (select * from t1 where a < 5) as t2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 2.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`t1` `idx_a`,`idx_ab`) */ `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`t1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3) `t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `t2`
+# Nested derived tables
+explain extended select /*+ no_bnl(t1@dt2)*/ * from
+(select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(`t1`@`dt2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select /*+ QB_NAME(`dt2`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`) `dt2`
+explain extended select /*+ no_index(t1@DT2)*/ * from
+(select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`DT2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select /*+ QB_NAME(`DT2`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`) `dt2`
+# Explicit QB name overrides the implicit one
+explain extended select /*+ no_index(t1@dt2)*/ * from
+(select count(*) from t1, (select /*+ qb_name(dt2)*/ * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 400 100.00
+2 DERIVED ALL NULL NULL NULL NULL 4 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+3 DERIVED t1 ALL NULL NULL NULL NULL 100 4.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`dt2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select /*+ QB_NAME(`dt2`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`) `dt2`
+# Both hints are applied
+explain extended select /*+ no_index(t1@dt1) no_bnl(t1@dt2)*/ * from
+(select count(*) from t1, (select * from t1 where a < 5) dt1) as dt2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 400 100.00
+2 DERIVED ALL NULL NULL NULL NULL 4 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+3 DERIVED t1 ALL NULL NULL NULL NULL 100 4.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_INDEX(`t1`@`dt1`) NO_BNL(`t1`@`dt2`) */ `dt2`.`count(*)` AS `count(*)` from (/* select#2 */ select /*+ QB_NAME(`dt2`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select /*+ QB_NAME(`dt1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`) `dt2`
+# Nested derived tables with ambiguous names, hint is ignored
+explain extended select /*+ no_index(t1@t1)*/* from
+(select count(*) from t1, (select * from t1 where a < 5) t1) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Warning 4256 Query block name `t1` is ambiguous for NO_INDEX hint
+Note 1003 /* select#1 */ select `t1`.`count(*)` AS `count(*)` from (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `t1`) `t1`
+# The hint cannot be applied to a derived table with UNION
+explain extended select /*+ no_index(t2@t1)*/* from
+(select * from t1 where a < 3 union select * from t2 where a < 9) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 9 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 1 100.00 Using index condition
+3 UNION t2 ALL NULL NULL NULL NULL 100 8.00 Using where
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4257 Implicit query block name `t1` is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for NO_INDEX hint
+Note 1003 /* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3 union /* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`a` < 9) `t1`
+explain extended select /*+ no_index(t1@t1)*/* from
+(select * from t1 where a < 3 union select * from t2 where a < 9) as t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 9 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 1 100.00 Using index condition
+3 UNION t2 ALL NULL NULL NULL NULL 100 8.00 Using where
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4257 Implicit query block name `t1` is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for NO_INDEX hint
+Note 1003 /* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 3 union /* select#3 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`a` < 9) `t1`
+# Test INSERT..SELECT
+explain extended insert into t2 select /*+ no_bnl(t2@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+2 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 insert into `test`.`t2` /* select#1 */ select /*+ NO_BNL(`t2`@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`
+# Test MERGE and NO_MERGE hints
+explain extended select /*+ merge(@dt)*/ * from
+(select * from (select t1.* from t1, t2 where t1.a > t2.a) as dt1) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+2 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 /* select#1 */ select /*+ MERGE(@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`
+explain extended select /*+ no_merge(@dt)*/ * from
+(select * from (select t1.* from t1, t2 where t1.a > t2.a) as dt1) as dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED ALL NULL NULL NULL NULL 10000 100.00
+3 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+3 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_MERGE(@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#2 */ select /*+ QB_NAME(`dt`) */ `dt1`.`a` AS `a`,`dt1`.`b` AS `b`,`dt1`.`c` AS `c` from (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt1`) `dt`
+# Multiple levels of nested derived tables, all hints are applied
+explain extended
+select /*+ no_merge(dv) no_bnl(t2@dt) */ * from (
+select /*+ no_merge(du) */ * from (
+select /*+ no_merge(dt) */ * from (
+select t1.* from t1, t2 where t1.a > t2.a
+) dt
+) du
+) dv;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+2 DERIVED ALL NULL NULL NULL NULL 10000 100.00
+3 DERIVED ALL NULL NULL NULL NULL 10000 100.00
+4 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+4 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_MERGE(`dt`@`select#3`) NO_MERGE(`du`@`select#2`) NO_MERGE(`dv`@`select#1`) NO_BNL(`t2`@`dt`) */ `dv`.`a` AS `a`,`dv`.`b` AS `b`,`dv`.`c` AS `c` from (/* select#2 */ select `du`.`a` AS `a`,`du`.`b` AS `b`,`du`.`c` AS `c` from (/* select#3 */ select `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#4 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`) `du`) `dv`
+# ======================================
+# Test CTEs
+# By default BNL and index access to t1 are used.
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 with cte as (/* select#2 */ select count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`)/* select#1 */ select `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(t1@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`)/* select#1 */ select /*+ NO_BNL(`t1`@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`)/* select#1 */ select /*+ NO_BNL(@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`)/* select#1 */ select /*+ NO_INDEX(`t1`@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte) no_index(t1@dt1)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 400 100.00
+2 DERIVED ALL NULL NULL NULL NULL 4 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+3 DERIVED t1 ALL NULL NULL NULL NULL 100 4.00 Using where
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select /*+ QB_NAME(`dt1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`)/* select#1 */ select /*+ NO_INDEX(`t1`@`cte`) NO_INDEX(`t1`@`dt1`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+explain extended
+with cte as (select count(*) from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@dt1 idx_a) no_bnl(@cte)*/ * from cte;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 300 100.00
+2 DERIVED ALL NULL NULL NULL NULL 3 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index
+3 DERIVED t1 range idx_ab idx_ab 5 NULL 3 100.00 Using index condition
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte`) */ count(0) AS `count(*)` from `test`.`t1` join (/* select#3 */ select /*+ QB_NAME(`dt1`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1`)/* select#1 */ select /*+ NO_INDEX(`t1`@`dt1` `idx_a`) NO_BNL(@`cte`) */ `cte`.`count(*)` AS `count(*)` from `cte`
+# Ambiguity: multiple occurencies of `cte`, the hint is ignored
+explain extended
+with cte as (select count(*) as cnt from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_bnl(@cte)*/ * from cte where cnt > 10
+union
+select * from cte where cnt < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00 Using where
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+4 UNION ALL NULL NULL NULL NULL 200 100.00 Using where
+5 DERIVED ALL NULL NULL NULL NULL 2 100.00
+5 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+6 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4256 Query block name `cte` is ambiguous for NO_BNL hint
+Note 1003 with cte as (/* select#2 */ select count(0) AS `cnt` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1` having `cnt` > 10)/* select#1 */ select `cte`.`cnt` AS `cnt` from `cte` where `cte`.`cnt` > 10 union /* select#4 */ select `cte`.`cnt` AS `cnt` from `cte` where `cte`.`cnt` < 100
+# However, if CTE occurencies have different aliases, the hint can be applied
+explain extended
+with cte as (select count(*) as cnt from t1, (select * from t1 where a < 5) dt1)
+select /*+ no_index(t1@cte1)*/ * from cte as cte1 where cnt > 10
+union
+select * from cte where cnt < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00 Using where
+2 DERIVED ALL NULL NULL NULL NULL 2 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00 Using join buffer (flat, BNL join)
+3 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+4 UNION ALL NULL NULL NULL NULL 200 100.00 Using where
+5 DERIVED ALL NULL NULL NULL NULL 2 100.00
+5 DERIVED t1 index NULL idx_a 5 NULL 100 100.00 Using index; Using join buffer (flat, BNL join)
+6 DERIVED t1 range idx_a,idx_ab idx_a 5 NULL 2 100.00 Using index condition
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Note 1003 with cte as (/* select#2 */ select /*+ QB_NAME(`cte1`) */ count(0) AS `cnt` from `test`.`t1` join (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 5) `dt1` having `cnt` > 10)/* select#1 */ select /*+ NO_INDEX(`t1`@`cte1`) */ `cte1`.`cnt` AS `cnt` from `cte` `cte1` where `cte1`.`cnt` > 10 union /* select#4 */ select `cte`.`cnt` AS `cnt` from `cte` where `cte`.`cnt` < 100
+# ======================================
+# Test views
+create view v1 as select * from t1 where a < 100;
+# Default execution plan
+explain extended select *
+from v1, v1 as v2 where v1.a = v2.a and v1.a < 3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_a,idx_ab idx_a 5 NULL 1 100.00 Using index condition
+1 SIMPLE t1 ref idx_a,idx_ab idx_a 5 test.t1.a 1 100.00
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 3 and `test`.`t1`.`a` < 100 and `test`.`t1`.`a` < 100
+explain extended
+select /*+ index(t1@v1 idx_ab) no_index(t1@`v2`)*/ *
+from v1, v1 as v2 where v1.a = v2.a and v1.a < 3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 2 100.00 Using index condition
+1 SIMPLE t1 ALL NULL NULL NULL NULL 100 99.00 Using where; Using join buffer (flat, BNL join)
+Warnings:
+Note 1003 select /*+ INDEX(`t1`@`v1` `idx_ab`) NO_INDEX(`t1`@`v2`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 3 and `test`.`t1`.`a` < 100 and `test`.`t1`.`a` < 100
+# Nested views
+create view v2 as select * from v1 where a < 300;
+# Default execution plan
+explain extended select * from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL idx_a,idx_ab NULL NULL NULL 100 94.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 300 and `test`.`t1`.`a` < 100
+# Addressing an object inside a nested view
+explain extended select /*+ index(t1@`v1` idx_ab)*/ * from v2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range idx_ab idx_ab 5 NULL 99 100.00 Using index condition
+Warnings:
+Note 1003 select /*+ INDEX(`t1`@`v1` `idx_ab`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`a` < 300 and `test`.`t1`.`a` < 100
+create view v3 as select * from t1 union select * from t2;
+# Unable to apply the hint to a view with UNION
+explain extended select /*+ no_index(t1@v3) */ * from v3;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 200 100.00
+2 DERIVED t1 ALL NULL NULL NULL NULL 100 100.00
+3 UNION t2 ALL NULL NULL NULL NULL 100 100.00
+NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL
+Warnings:
+Warning 4257 Implicit query block name `v3` is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for NO_INDEX hint
+Note 1003 /* select#1 */ select `v3`.`a` AS `a`,`v3`.`b` AS `b`,`v3`.`c` AS `c` from `test`.`v3`
+# Ambiguity: view `v1` appears two times - should warn and ignore hint
+explain extended select /*+ index(t2@v1) */ * from v1,
+(select a from v1 where b > 5) dt;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL idx_a,idx_ab NULL NULL NULL 100 94.00 Using where
+1 PRIMARY ALL NULL NULL NULL NULL 99 100.00 Using join buffer (flat, BNL join)
+2 DERIVED t1 range idx_a,idx_ab idx_ab 5 NULL 99 90.20 Using where; Using index
+Warnings:
+Warning 4256 Query block name `v1` is ambiguous for INDEX hint
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`dt`.`a` AS `a` from `test`.`t1` join (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`b` > 5 and `test`.`t1`.`a` < 100) `dt` where `test`.`t1`.`a` < 100
+# Implicit QB names are not supported inside views
+create view v4 as select /*+ no_bnl(t2@dt)*/ * from
+(select t1.* from t1, t2 where t1.a > t2.a) as dt;
+Warnings:
+Warning 4242 Implicit query block names are ignored for hints specified within VIEWs
+show create view v4;
+View Create View character_set_client collation_connection
+v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS select `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c` from (`t1` join `t2`) where `t1`.`a` > `t2`.`a`) `dt` latin1 latin1_swedish_ci
+# However, a derived table inside a view can be addressed from outer query
+create view v5 as select dt.a from
+t1, (select t1.* from t1, t2 where t1.a > t2.a) as dt where t1.a=dt.a;
+# Addressing a single table
+explain extended select /*+ no_bnl(t2@dt) */* from v5;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 index idx_a,idx_ab idx_a 5 NULL 100 100.00 Using where; Using index
+1 PRIMARY ref key0 key0 5 test.t1.a 100 100.00
+3 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+3 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(`t2`@`dt`) */ `dt`.`a` AS `a` from `test`.`t1` join (/* select#3 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt` where `dt`.`a` = `test`.`t1`.`a`
+# Addressing the whole derived table
+explain extended select /*+ no_bnl(@dt) */* from v5;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 index idx_a,idx_ab idx_a 5 NULL 100 100.00 Using where; Using index
+1 PRIMARY ref key0 key0 5 test.t1.a 100 100.00
+3 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+3 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(@`dt`) */ `dt`.`a` AS `a` from `test`.`t1` join (/* select#3 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt` where `dt`.`a` = `test`.`t1`.`a`
+# Derived tables inside views can be addressed by their aliases
+explain extended select /*+ no_bnl(t2@dt) */ * from v4;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY ALL NULL NULL NULL NULL 10000 100.00
+3 DERIVED t1 ALL idx_a,idx_ab NULL NULL NULL 100 100.00
+3 DERIVED t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select /*+ NO_BNL(`t2`@`dt`) */ `dt`.`a` AS `a`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from (/* select#3 */ select /*+ QB_NAME(`dt`) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` > `test`.`t2`.`a`) `dt`
+drop view v1, v2, v3, v4, v5;
+# ======================================
+# Not supported for DML, check presence of warnings
+explain extended
+update /*+ no_range_optimization(t1@dt)*/ t2,
+(select a from t1 where a > 10) dt
+set b=1 where t2.a = dt.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 100.00 Using where
+1 PRIMARY ref key0 key0 5 test.t2.a 9 100.00
+2 DERIVED t1 range idx_a,idx_ab idx_ab 5 NULL 92 100.00 Using where; Using index
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_RANGE_OPTIMIZATION hint
+Note 1003 /* select#1 */ update `test`.`t2` join (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 10) `dt` set `test`.`t2`.`b` = 1 where `dt`.`a` = `test`.`t2`.`a`
+explain extended
+delete /*+ no_index(t1@dt)*/ from t2
+where t2.a in
+(select * from (select a from t1 where a > 10) dt where dt.a > 20);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 80.00 Using where
+1 PRIMARY eq_ref distinct_key distinct_key 5 test.t2.a 1 100.00
+3 DERIVED t1 range idx_a,idx_ab idx_ab 5 NULL 84 100.00 Using where; Using index
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_INDEX hint
+Note 1003 /* select#1 */ delete from `test`.`t2` using (/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 10 and `test`.`t1`.`a` > 20) `dt` where `dt`.`a` = `test`.`t2`.`a` and `test`.`t2`.`a` > 20
+# ======================================
+# Objects in triggers and stored functions must not be visible for hints
+create table t3 (a int, b int);
+# Trigger with derived table inside
+create trigger tr1 before insert on t3
+for each row
+begin
+set new.b = (select max(a) from
+(select a from t1 where a < new.a) dt);
+end|
+# Warning expected
+explain extended select /*+ no_index(t1@dt) */ max(a) from t3 where a<2;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_INDEX hint
+Note 1003 select max(NULL) AS `max(a)` from `test`.`t3` where 0
+# Stored function with derived table inside
+create function get_max(p_a int) returns int
+return (select max(a) from
+(select a from t1 where a < p_a) dt);
+# Warning expected
+explain extended select /*+ no_index(t1@dt) */ a, get_max(a) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 index NULL idx_a 5 NULL 100 100.00 Using index
+Warnings:
+Warning 4220 Query block name `dt` is not found for NO_INDEX hint
+Note 1003 select `test`.`t1`.`a` AS `a`,`get_max`(`test`.`t1`.`a`) AS `get_max(a)` from `test`.`t1`
+drop function get_max;
+drop table t1, t2, t3;
+set optimizer_switch = default;
diff --git a/mysql-test/main/opt_hints_impl_qb_name.test b/mysql-test/main/opt_hints_impl_qb_name.test
new file mode 100644
index 0000000000000..0c4c427380300
--- /dev/null
+++ b/mysql-test/main/opt_hints_impl_qb_name.test
@@ -0,0 +1,9 @@
+set optimizer_switch = 'derived_merge=on';
+
+--source opt_hints_impl_qb_name.inc
+
+set optimizer_switch = 'derived_merge=off';
+
+--source opt_hints_impl_qb_name.inc
+
+set optimizer_switch = default;
diff --git a/sql/opt_hints.cc b/sql/opt_hints.cc
index 230afd47d7d95..becd69c94ac56 100644
--- a/sql/opt_hints.cc
+++ b/sql/opt_hints.cc
@@ -15,10 +15,12 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "my_global.h"
+#include "opt_hints_structs.h"
#include "sql_class.h"
#include "sql_lex.h"
#include "sql_select.h"
#include "opt_hints.h"
+#include "opt_trace.h"
/**
Information about hints. Must be in sync with opt_hints_enum.
@@ -46,15 +48,15 @@ struct st_opt_hint_info opt_hint_info[]=
{{STRING_WITH_LEN("JOIN_SUFFIX")}, false, true, true},
{{STRING_WITH_LEN("JOIN_ORDER")}, false, true, true},
{{STRING_WITH_LEN("JOIN_FIXED_ORDER")}, false, true, false},
- {{STRING_WITH_LEN("DERIVED_CONDITION_PUSHDOWN")}, false, false, false},
- {{STRING_WITH_LEN("MERGE")}, true, false, false},
- {{STRING_WITH_LEN("SPLIT_MATERIALIZED")}, false, false, false},
+ {{STRING_WITH_LEN("DERIVED_CONDITION_PUSHDOWN")}, false, false, false},
+ {{STRING_WITH_LEN("MERGE")}, true, false, false},
+ {{STRING_WITH_LEN("SPLIT_MATERIALIZED")}, false, false, false},
{{STRING_WITH_LEN("INDEX")}, false, true, false},
{{STRING_WITH_LEN("JOIN_INDEX")}, false, true, false},
{{STRING_WITH_LEN("GROUP_INDEX")}, false, true, false},
{{STRING_WITH_LEN("ORDER_INDEX")}, false, true, false},
{{STRING_WITH_LEN("ROWID_FILTER")}, false, true, false},
- {{STRING_WITH_LEN("INDEX_MERGE")}, false, false, false},
+ {{STRING_WITH_LEN("INDEX_MERGE")}, false, false, false},
{null_clex_str, 0, 0, 0}
};
@@ -84,7 +86,6 @@ int cmp_lex_string(const LEX_CSTRING &s, const LEX_CSTRING &t,
(const uchar*)t.str, t.length);
}
-
/*
This is a version of push_warning_printf() guaranteeing no escalation of
the warning to the level of error
@@ -137,7 +138,9 @@ void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
str.append(opt_hint_info[hint_type].hint_type);
/* ER_WARN_UNKNOWN_QB_NAME with two arguments */
- if (err_code == ER_WARN_UNKNOWN_QB_NAME)
+ if (err_code == ER_WARN_UNKNOWN_QB_NAME ||
+ err_code == ER_WARN_AMBIGUOUS_QB_NAME ||
+ err_code == ER_WARN_IMPLICIT_QB_NAME_FOR_UNION)
{
String qb_name_str;
append_identifier(thd, &qb_name_str, qb_name_arg->str, qb_name_arg->length);
@@ -287,6 +290,95 @@ static Opt_hints_qb *find_hints_by_select_number(Parse_context *pc,
return qb;
}
+/**
+ Helper function to find_qb_hints whereby it matches a qb_name to
+ an alias of a derived table, view or CTE used in the current query.
+ For example, for query
+ `select * from (select ... from t1 ...) as DT`
+ and given qb_name "DT", this function will return the query block
+ corresponding to the derived table DT, just like if the name was specified
+ explicitly using the QB_NAME hint:
+ `select * from (select / *+ QB_NAME(DT) * / ... from t1 ...) as DT`
+
+ For query
+ `select * from v1, v1 as v2 where v1.a = v2.a and v1.a < 3`
+ and given qb_name "v2", this function will return the query block
+ corresponding to the view v2.
+
+ For query
+ `with lda as (select ... from t1 ...)
+ select * from lda`
+ and given qb_name "lda", this function will return the query block
+ corresponding to the CTE "lda", just like if the name was specified
+ explicitly using the QB_NAME hint:
+ `with lda as (select / *+ QB_NAME(lda) * / ... from t1 ...)
+ select * from lda`
+
+ Note: Implicit QB names are only supported for SELECTs. DML operations
+ (UPDATE, DELETE, INSERT) only support explicit QB names. This is caused by
+ the fact that optimizer hints are resolved before `open_tables()`
+ at `Sql_cmd_dml::prepare()`.
+
+ @return the pair: - result code
+ - matching query block hints object, if it exists,
+ and NULL otherwise
+ */
+
+enum class implicit_qb_result
+{
+ OK, // Found exactly one match, success
+ // Failure statuses:
+ NOT_FOUND, // No matches found
+ AMBIGUOUS, // More than one alias matches qb_name in the current query
+ UNION // DT/view/CTE has UNION/EXCEPT/INTERSECT inside
+ // (i.e., multiple query blocks), so the hint cannot be resolved
+ // unambiguously
+};
+
+static std::pair
+find_hints_by_implicit_qb_name(Parse_context *pc, const Lex_ident_sys &qb_name)
+{
+ Opt_hints_qb *qb= nullptr;
+
+ // Traverse the global table list to find all derived tables and views
+ for (TABLE_LIST *tbl= pc->thd->lex->query_tables; tbl; tbl= tbl->next_global)
+ {
+ // Skip if neither a derived table nor a view
+ if (tbl->is_non_derived())
+ continue;
+
+ // Check if the alias equals the implicit QB name
+ if (cmp_lex_string(tbl->alias, qb_name, system_charset_info))
+ continue; // not a match, continue to next table
+
+ /*
+ If `qb` was already set before, this means there are multiple tables with
+ same alias in the query. The name cannot be resolved unambiguously.
+ */
+ if (qb)
+ return {implicit_qb_result::AMBIGUOUS, nullptr};
+
+ SELECT_LEX *child_select= tbl->get_unit()->first_select();
+ /*
+ Check if the derived table/view does not contain UNION, because
+ implicit QB names for UNIONs are ambiguous - we do not know which SELECT
+ should the hint be applied to. So we only support implicit names
+ for single-SELECT derived tables/views.
+ */
+ if (child_select->next_select())
+ return {implicit_qb_result::UNION, nullptr};
+
+ Parse_context child_ctx(pc, child_select);
+ /*
+ qb should be set only this one time. Ambiguous references to
+ the same query block will fail on subsequent iterations (see above).
+ */
+ qb= get_qb_hints(&child_ctx);
+ }
+
+ return {(qb ? implicit_qb_result::OK : implicit_qb_result::NOT_FOUND), qb};
+}
+
/**
Find existing Opt_hints_qb object, print warning
@@ -316,13 +408,37 @@ Opt_hints_qb *find_qb_hints(Parse_context *pc,
if (qb_by_name == nullptr)
qb_by_number= find_hints_by_select_number(pc, qb_name);
+ Opt_hints_qb *qb_by_implicit_name= nullptr;
+ if (qb_by_name == nullptr && qb_by_number == nullptr)
+ {
+ std::pair find_res=
+ find_hints_by_implicit_qb_name(pc, qb_name);
+ if (find_res.first == implicit_qb_result::AMBIGUOUS)
+ {
+ // Warn on ambiguous derived table name
+ print_warn(pc->thd, ER_WARN_AMBIGUOUS_QB_NAME,
+ hint_type, hint_state, &qb_name,
+ nullptr, nullptr, nullptr);
+ return nullptr;
+ }
+ if (find_res.first == implicit_qb_result::UNION)
+ {
+ print_warn(pc->thd, ER_WARN_IMPLICIT_QB_NAME_FOR_UNION,
+ hint_type, hint_state, &qb_name,
+ nullptr, nullptr, nullptr);
+ return nullptr;
+ }
+ qb_by_implicit_name= find_res.second;
+ }
+
// C++-style comment here, otherwise compiler warns of /* within comment.
// We don't allow implicit query block names to be specified for hints local
// to a view (e.g. CREATE VIEW v1 AS SELECT /*+ NO_ICP(@`select#2` t1) ...
// because of select numbering issues. When we're ready to fix that, then we
// can remove this gate.
+ // Implicit QB naming using DT/view aliases is also not supported inside views
if (pc->thd->lex->sql_command == SQLCOM_CREATE_VIEW &&
- qb_by_number)
+ (qb_by_number || qb_by_implicit_name))
{
print_warn(pc->thd, ER_WARN_NO_IMPLICIT_QB_NAMES_IN_VIEW,
hint_type, hint_state, &qb_name,
@@ -330,10 +446,21 @@ Opt_hints_qb *find_qb_hints(Parse_context *pc,
return nullptr;
}
- Opt_hints_qb *qb= qb_by_name ? qb_by_name : qb_by_number;
+ Opt_hints_qb *qb= qb_by_name ? qb_by_name :
+ (qb_by_number ? qb_by_number : qb_by_implicit_name);
if (qb == nullptr)
+ {
print_warn(pc->thd, ER_WARN_UNKNOWN_QB_NAME, hint_type, hint_state,
&qb_name, NULL, NULL, NULL);
+ }
+ else if (qb == qb_by_implicit_name && qb->get_name().length == 0)
+ {
+ /*
+ If the block is addressed by an implicit name, assign a name to the block,
+ so it is properly printed in warnings
+ */
+ qb->set_name(qb_name);
+ }
return qb;
}
@@ -1656,7 +1783,7 @@ bool is_compound_hint(opt_hints_enum type_arg)
/*
@brief
Perform "Hint Resolution" for Optimizer Hints (see opt_hints.h for
- definition)
+ definition).
@detail
Hints use "Explain select numbering", so this must be called after the
@@ -1665,16 +1792,13 @@ bool is_compound_hint(opt_hints_enum type_arg)
On the other hand, this must be called before the first attempt to check
any hint.
*/
-
void LEX::resolve_optimizer_hints()
{
+ if (selects_for_hint_resolution.is_empty())
+ return;
+
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
- SCOPE_EXIT([&] () mutable {
- selects_for_hint_resolution.empty();
- if (arena)
- thd->restore_active_arena(arena, &backup);
- });
List_iterator it(selects_for_hint_resolution);
SELECT_LEX *sel;
@@ -1685,8 +1809,13 @@ void LEX::resolve_optimizer_hints()
Parse_context pc(thd, sel);
sel->parsed_optimizer_hints->resolve(&pc);
}
+
+ selects_for_hint_resolution.empty();
+ if (arena)
+ thd->restore_active_arena(arena, &backup);
}
+
#ifndef DBUG_OFF
static char dbug_print_hint_buf[64];
diff --git a/sql/opt_hints.h b/sql/opt_hints.h
index c0973f48ace72..d5b63be5c4378 100644
--- a/sql/opt_hints.h
+++ b/sql/opt_hints.h
@@ -113,6 +113,7 @@
#include
#include "my_config.h"
+#include "opt_hints_structs.h"
#include "sql_alloc.h"
#include "sql_list.h"
#include "mem_root_array.h"
diff --git a/sql/opt_hints_parser.cc b/sql/opt_hints_parser.cc
index 743c8339f0785..4161dfb21f143 100644
--- a/sql/opt_hints_parser.cc
+++ b/sql/opt_hints_parser.cc
@@ -53,12 +53,14 @@ void append_table_name(THD *thd, String *str, const LEX_CSTRING &table_name,
static const Lex_ident_sys null_ident_sys;
+
Parse_context::Parse_context(THD *thd, st_select_lex *select)
: thd(thd),
mem_root(thd->mem_root),
select(select)
{}
+
Parse_context::Parse_context(Parse_context *pc, st_select_lex *select)
: thd(pc->thd),
mem_root(pc->mem_root),
@@ -1283,6 +1285,20 @@ bool Parser::Hint_list::resolve(Parse_context *pc) const
if (!get_qb_hints(pc))
return true;
+ /*
+ QB_NAME hints are resolved first so following hints can be attached to
+ the pre-configured query blocks
+ */
+ for (Hint_list::iterator li= this->begin(); li != this->end(); ++li)
+ {
+ Parser::Hint &hint= *li;
+ if (const Qb_name_hint &qb_hint= hint)
+ {
+ if (qb_hint.resolve(pc))
+ return true;
+ }
+ }
+
for (Hint_list::iterator li= this->begin(); li != this->end(); ++li)
{
Parser::Hint &hint= *li;
@@ -1296,11 +1312,6 @@ bool Parser::Hint_list::resolve(Parse_context *pc) const
if (index_hint.resolve(pc))
return true;
}
- else if (const Qb_name_hint &qb_hint= hint)
- {
- if (qb_hint.resolve(pc))
- return true;
- }
else if (const Max_execution_time_hint &max_hint= hint)
{
if (max_hint.resolve(pc))
@@ -1321,6 +1332,11 @@ bool Parser::Hint_list::resolve(Parse_context *pc) const
if (join_order_hint.resolve(pc))
return true;
}
+ else if (const Qb_name_hint &qb_hint __attribute__((unused)) = hint)
+ {
+ // QB_NAME hints have been resolved earlier
+ continue;
+ }
else {
DBUG_ASSERT(0);
}
diff --git a/sql/opt_hints_parser.h b/sql/opt_hints_parser.h
index 272982b8ae31d..996389100371d 100644
--- a/sql/opt_hints_parser.h
+++ b/sql/opt_hints_parser.h
@@ -19,6 +19,7 @@
*/
#include "lex_ident_sys.h"
+#include "opt_hints_structs.h"
#include "simple_tokenizer.h"
#include "sql_list.h"
#include "sql_string.h"
@@ -28,46 +29,14 @@
class st_select_lex;
class Opt_hints_qb;
-/**
- Hint types, MAX_HINT_ENUM should be always last.
- This enum should be synchronized with opt_hint_info
- array(see opt_hints.cc).
-*/
-enum opt_hints_enum
-{
- BKA_HINT_ENUM= 0,
- BNL_HINT_ENUM,
- ICP_HINT_ENUM,
- MRR_HINT_ENUM,
- NO_RANGE_HINT_ENUM,
- QB_NAME_HINT_ENUM,
- MAX_EXEC_TIME_HINT_ENUM,
- SEMIJOIN_HINT_ENUM,
- SUBQUERY_HINT_ENUM,
- JOIN_PREFIX_HINT_ENUM,
- JOIN_SUFFIX_HINT_ENUM,
- JOIN_ORDER_HINT_ENUM,
- JOIN_FIXED_ORDER_HINT_ENUM,
- DERIVED_CONDITION_PUSHDOWN_HINT_ENUM,
- MERGE_HINT_ENUM,
- SPLIT_MATERIALIZED_HINT_ENUM,
- INDEX_HINT_ENUM,
- JOIN_INDEX_HINT_ENUM,
- GROUP_INDEX_HINT_ENUM,
- ORDER_INDEX_HINT_ENUM,
- ROWID_FILTER_HINT_ENUM,
- INDEX_MERGE_HINT_ENUM,
- MAX_HINT_ENUM // This one must be the last in the list
-};
-
-
/**
Environment data for the name resolution phase
*/
-struct Parse_context {
- THD * const thd; //github.com/< Current thread handler
- MEM_ROOT *mem_root; //github.com/< Current MEM_ROOT
- st_select_lex * select; //github.com/< Current SELECT_LEX object
+struct Parse_context
+{
+ THD * const thd;
+ MEM_ROOT *mem_root;
+ st_select_lex *select;
Parse_context(THD *thd, st_select_lex *select);
Parse_context(Parse_context *pc, st_select_lex *select);
diff --git a/sql/opt_hints_structs.h b/sql/opt_hints_structs.h
new file mode 100644
index 0000000000000..a4835e3982486
--- /dev/null
+++ b/sql/opt_hints_structs.h
@@ -0,0 +1,53 @@
+#ifndef OPT_HINTS_STRUCTS_H
+#define OPT_HINTS_STRUCTS_H
+/*
+ Copyright (c) 2026, MariaDB
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2 of
+ the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
+*/
+
+/**
+ Hint types, MAX_HINT_ENUM should be always last.
+ This enum should be synchronized with opt_hint_info
+ array(see opt_hints.cc).
+*/
+enum opt_hints_enum
+{
+ BKA_HINT_ENUM= 0,
+ BNL_HINT_ENUM,
+ ICP_HINT_ENUM,
+ MRR_HINT_ENUM,
+ NO_RANGE_HINT_ENUM,
+ QB_NAME_HINT_ENUM,
+ MAX_EXEC_TIME_HINT_ENUM,
+ SEMIJOIN_HINT_ENUM,
+ SUBQUERY_HINT_ENUM,
+ JOIN_PREFIX_HINT_ENUM,
+ JOIN_SUFFIX_HINT_ENUM,
+ JOIN_ORDER_HINT_ENUM,
+ JOIN_FIXED_ORDER_HINT_ENUM,
+ DERIVED_CONDITION_PUSHDOWN_HINT_ENUM,
+ MERGE_HINT_ENUM,
+ SPLIT_MATERIALIZED_HINT_ENUM,
+ INDEX_HINT_ENUM,
+ JOIN_INDEX_HINT_ENUM,
+ GROUP_INDEX_HINT_ENUM,
+ ORDER_INDEX_HINT_ENUM,
+ ROWID_FILTER_HINT_ENUM,
+ INDEX_MERGE_HINT_ENUM,
+ MAX_HINT_ENUM // This one must be the last in the list
+};
+
+#endif /* OPT_HINTS_STRUCTS_H */
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 272002ffdc273..ad79a80cc11de 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -12388,3 +12388,7 @@ ER_SLAVE_INCOMPATIBLE_TABLE_DEF
eng "Table structure for binlog event is not compatible with the table definition on this slave: %s"
ER_UNSUPPORTED_DATA_TYPE_ATTRIBUTE
eng "Data type '%-.64s' doesn't support %s attribute."
+ER_WARN_AMBIGUOUS_QB_NAME
+ eng "Query block name %s is ambiguous for %s hint"
+ER_WARN_IMPLICIT_QB_NAME_FOR_UNION
+ eng "Implicit query block name %s is not supported for derived tables and views with UNION/EXCEPT/INTERSECT and is ignored for %s hint"
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 059cf17e75bf6..8ac717a892b0c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5809,8 +5809,17 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
uint counter;
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
DBUG_ENTER("open_normal_and_derived_tables");
- if (open_tables(thd, &tables, &counter, flags, &prelocking_strategy) ||
- mysql_handle_derived(thd->lex, dt_phases))
+ if (open_tables(thd, &tables, &counter, flags, &prelocking_strategy))
+ goto end;
+
+ // Process initialization phase if it is requested in dt_phases
+ if ((dt_phases & DT_INIT) && mysql_handle_derived(thd->lex, DT_INIT))
+ goto end;
+
+ thd->lex->resolve_optimizer_hints();
+
+ // Process all phases remaining after DT_INIT
+ if (mysql_handle_derived(thd->lex, dt_phases & ~DT_INIT))
goto end;
DBUG_RETURN(0);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1fce0eb6014c2..92b9da85d8ac5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3539,7 +3539,6 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
*/
lex->first_lists_tables_same();
lex->fix_first_select_number();
- lex->resolve_optimizer_hints();
/* should be assigned after making first tables same */
all_tables= lex->query_tables;
/* set context for commands which do not use setup_tables */
@@ -4674,6 +4673,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
select_lex->table_list.first= second_table;
select_lex->context.table_list=
select_lex->context.first_name_resolution_table= second_table;
+ lex->resolve_optimizer_hints();
res= mysql_insert_select_prepare(thd, result);
Write_record write;
if (!res &&
@@ -6129,6 +6129,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0)))
{
+ lex->resolve_optimizer_hints();
if (lex->describe)
{
/*
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c572cb3d79970..7bab50950309d 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1564,6 +1564,7 @@ static int mysql_test_select(Prepared_statement *stmt,
DT_INIT | DT_PREPARE))
goto error;
+ lex->resolve_optimizer_hints();
thd->lex->used_tables= 0; // Updated by setup_fields
/*
@@ -2304,7 +2305,6 @@ static bool check_prepared_statement(Prepared_statement *stmt)
lex->first_lists_tables_same();
lex->fix_first_select_number();
- lex->resolve_optimizer_hints();
tables= lex->query_tables;
/* set context for commands which do not use setup_tables */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b8fbbe2f62f58..2bc18527cef10 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -34748,7 +34748,7 @@ bool Sql_cmd_dml::prepare(THD *thd)
MYSQL_DML_START(thd);
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
-
+ lex->resolve_optimizer_hints();
if (open_tables_for_query(thd, lex->query_tables, &table_count, 0,
get_dml_prelocking_strategy()))
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2b4aa9ce702c7..29134e736055e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1375,6 +1375,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
if (mysqld_show_create_get_fields(thd, table_list, &field_list, &buffer))
goto exit;
+ thd->lex->resolve_optimizer_hints();
if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 450a1b3a9756b..7b88a41323f10 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -559,6 +559,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
/* prepare select to resolve all fields */
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
+ lex->resolve_optimizer_hints();
if (unit->prepare(unit->derived, 0, 0))
{
/*
diff --git a/sql/table.cc b/sql/table.cc
index e81ca13a4db4d..b673b08386e67 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -10108,7 +10108,10 @@ static inline bool derived_table_optimization_done(TABLE_LIST *table)
@brief
Initialize this derived table/view
- @param thd Thread handle
+ @param
+ thd Thread handle
+ init_view TRUE when called from mysql_derived_init (first call)
+ FALSE when called from mysql_derived_prepare (second call)
@details
This function makes initial preparations of this derived table/view for
@@ -10186,9 +10189,18 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
!this->opt_hints_table) // Table hints are not adjusted yet
select_lex->opt_hints_qb->fix_hints_for_derived_table(this);
+ /*
+ (1) Allow merging during initialization (first call, init_view == true),
+ while optimizer hints are not yet resolved. By the time of
+ the second call (preparation, init_view == false) optimizer hints are
+ already resolved, so the previous choice can be re-considered.
+ (2) Prefer optimizer hint setting for this particular table.
+ If there is no hint then fall back to the optimizer switch setting.
+ */
bool is_derived_merge_allowed=
+ init_view || // (1)
hint_table_state(thd, this, MERGE_HINT_ENUM,
- optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE));
+ optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE)); // (2)
if (!is_materialized_derived() && unit->can_be_merged() &&
/*
pFad - Phonifier reborn
Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy