mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-33281 Optimizer hints Cleanup: fix formatting, rename objects
This commit is contained in:
@@ -208,3 +208,30 @@ DROP PACKAGE test.pkg;
|
||||
#
|
||||
# End of 11.4 tests
|
||||
#
|
||||
#
|
||||
# Start of 11.7 tests
|
||||
#
|
||||
#
|
||||
# MDEV-33281 Implement optimizer hints like in MySQL
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1), (2);
|
||||
SELECT /*+BKA(a) BKA(å)*/ a.a FROM t1 a, t1 å;
|
||||
a
|
||||
1
|
||||
2
|
||||
1
|
||||
2
|
||||
SELECT a.a, A.a FROM t1 a, t1 A;
|
||||
ERROR 42000: Not unique table/alias: 'A'
|
||||
SELECT /*+BKA(a) BKA(A)*/ a.a FROM t1 a;
|
||||
a
|
||||
1
|
||||
2
|
||||
Warnings:
|
||||
Warning 4202 Hint BKA("A") is ignored as conflicting/duplicated
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 11.7 tests
|
||||
#
|
||||
|
@@ -204,3 +204,33 @@ DROP PACKAGE test.pkg;
|
||||
--echo #
|
||||
--echo # End of 11.4 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Start of 11.7 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-33281 Implement optimizer hints like in MySQL
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1), (2);
|
||||
|
||||
# Test that aliases are accent sensitive with lowercase-table-names=1
|
||||
# Test that table names in hints are also accent sensitive
|
||||
SELECT /*+BKA(a) BKA(å)*/ a.a FROM t1 a, t1 å;
|
||||
|
||||
# Test that aliases are case insensitive with lowercase-table-names=1
|
||||
--error ER_NONUNIQ_TABLE
|
||||
SELECT a.a, A.a FROM t1 a, t1 A;
|
||||
# Test that table names in hints are also case insensitive
|
||||
SELECT /*+BKA(a) BKA(A)*/ a.a FROM t1 a;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.7 tests
|
||||
--echo #
|
||||
|
@@ -189,3 +189,28 @@ DROP DATABASE MYSQL;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
#
|
||||
# Start of 11.7 tests
|
||||
#
|
||||
#
|
||||
# MDEV-33281 Implement optimizer hints like in MySQL
|
||||
#
|
||||
SET NAMES utf8mb4;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1), (2);
|
||||
SELECT /*+BKA(a) BKA(å)*/ a.a, å.a FROM t1 a, t1 å;
|
||||
a a
|
||||
1 1
|
||||
2 1
|
||||
1 2
|
||||
2 2
|
||||
SELECT /*+BKA(a) BKA(A)*/ a.a, A.a FROM t1 a, t1 A;
|
||||
a a
|
||||
1 1
|
||||
2 1
|
||||
1 2
|
||||
2 2
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 11.7 tests
|
||||
#
|
||||
|
@@ -187,3 +187,30 @@ DROP DATABASE MYSQL;
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 11.7 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-33281 Implement optimizer hints like in MySQL
|
||||
--echo #
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1), (2);
|
||||
|
||||
# Test that table aliases are accent sensitive with lowercase-table-names=0
|
||||
# Test that table names in hints are also accent sensitive
|
||||
SELECT /*+BKA(a) BKA(å)*/ a.a, å.a FROM t1 a, t1 å;
|
||||
|
||||
# Test that table aliases are case sensitive with lowercase-table-names=0
|
||||
# Test that table names in hints are also case sensitive
|
||||
SELECT /*+BKA(a) BKA(A)*/ a.a, A.a FROM t1 a, t1 A;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.7 tests
|
||||
--echo #
|
||||
|
@@ -1,4 +1,40 @@
|
||||
# WL#8017 Infrastructure for Optimizer Hints
|
||||
SET NAMES utf8mb4;
|
||||
# Testing that index names in hints are accent sensitive case insensitive
|
||||
CREATE TABLE t1 (a INT, ä INT, INDEX idx_a(a), INDEX idx_ä(ä));
|
||||
INSERT INTO t1 VALUES (1,1),(2,2);
|
||||
SELECT /*+ NO_MRR(t1 idx_a) */ a FROM t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
SELECT /*+ NO_MRR(t1 idx_A) */ a FROM t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
SELECT /*+ NO_MRR(t1 idx_å) */ a FROM t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
Warnings:
|
||||
Warning 4205 Unresolved index name `t1`@`select#1` `idx_å` for NO_MRR hint
|
||||
SELECT /*+ NO_MRR(t1 idx_a, idx_å, idx_A) */ a FROM t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
Warnings:
|
||||
Warning 4202 Hint NO_MRR(`t1` `idx_A`) is ignored as conflicting/duplicated
|
||||
Warning 4205 Unresolved index name `t1`@`select#1` `idx_å` for NO_MRR hint
|
||||
DROP TABLE t1;
|
||||
# Testing that query block names are accent sensitive case insensitive
|
||||
CREATE TABLE t1 (a INT);
|
||||
SELECT /*+ QB_NAME(a) BKA(t1@a) BKA(t1@A) */ * FROM t1;
|
||||
a
|
||||
Warnings:
|
||||
Warning 4202 Hint BKA(`t1`@`A`) is ignored as conflicting/duplicated
|
||||
SELECT /*+ QB_NAME(a) BKA(t1@a) BKA(t1@å) */ * FROM t1;
|
||||
a
|
||||
Warnings:
|
||||
Warning 4203 Query block name `å` is not found for BKA hint
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(f1 INT, f2 INT);
|
||||
INSERT INTO t1 VALUES
|
||||
(1,1),(2,2),(3,3);
|
||||
@@ -77,32 +113,78 @@ Warnings:
|
||||
Note 1003 select `test`.`t3`.`f1` AS `f1` from `test`.`t3` where `test`.`t3`.`f1` > 30 and `test`.`t3`.`f1` < 33
|
||||
# Turn off range access for PRIMARY key
|
||||
# Should use range access by f2_idx key
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t3 range PRIMARY,f2_idx f2_idx 4 NULL 2 100.00 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ `test`.`t3`.`f1` AS `f1` from `test`.`t3` where `test`.`t3`.`f1` > 30 and `test`.`t3`.`f1` < 33
|
||||
# Turn off range access for PRIMARY & f2_idx keys
|
||||
# Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t3 index PRIMARY,f2_idx PRIMARY 4 NULL 56 4.11 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) NO_RANGE_OPTIMIZATION(`t3`@`select#1` `f2_idx`) */ `test`.`t3`.`f1` AS `f1` from `test`.`t3` where `test`.`t3`.`f1` > 30 and `test`.`t3`.`f1` < 33
|
||||
# Turn off range access for all keys
|
||||
# Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t3 index PRIMARY,f2_idx PRIMARY 4 NULL 56 4.11 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1`) */ `test`.`t3`.`f1` AS `f1` from `test`.`t3` where `test`.`t3`.`f1` > 30 and `test`.`t3`.`f1` < 33
|
||||
# Turn off range access for PRIMARY & f2_idx keys
|
||||
# Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) NO_RANGE_OPTIMIZATION(t3 f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) NO_RANGE_OPTIMIZATION(t3 f2_idx) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t3 index PRIMARY,f2_idx PRIMARY 4 NULL 56 4.11 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) NO_RANGE_OPTIMIZATION(`t3`@`select#1` `f2_idx`) */ `test`.`t3`.`f1` AS `f1` from `test`.`t3` where `test`.`t3`.`f1` > 30 and `test`.`t3`.`f1` < 33
|
||||
# Create a clone of t3 with cyrillic names
|
||||
CREATE TABLE таблица (f1 INT NOT NULL, поле2 INT, поле3 VARCHAR(32),
|
||||
PRIMARY KEY(f1), KEY f2_индекс(f1), KEY f3_индекс(поле3))
|
||||
AS SELECT * FROM t3;
|
||||
ANALYZE TABLE таблица;
|
||||
Table Op Msg_type Msg_text
|
||||
test.таблица analyze status Engine-independent statistics collected
|
||||
test.таблица analyze status Table is already up to date
|
||||
# Turn off range access for PRIMARY key
|
||||
# Should use range access by f2_индекс key
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(таблица PRIMARY) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE таблица range PRIMARY,f2_индекс f2_индекс 4 NULL 2 100.00 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`таблица`@`select#1` `PRIMARY`) */ `test`.`таблица`.`f1` AS `f1` from `test`.`таблица` where `test`.`таблица`.`f1` > 30 and `test`.`таблица`.`f1` < 33
|
||||
# Turn off range access for PRIMARY & f2_индекс keys
|
||||
# Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(таблица PRIMARY, f2_индекс) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE таблица index PRIMARY,f2_индекс PRIMARY 4 NULL 56 4.11 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`таблица`@`select#1` `PRIMARY`) NO_RANGE_OPTIMIZATION(`таблица`@`select#1` `f2_индекс`) */ `test`.`таблица`.`f1` AS `f1` from `test`.`таблица` where `test`.`таблица`.`f1` > 30 and `test`.`таблица`.`f1` < 33
|
||||
# Turn off range access for all keys
|
||||
# Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(таблица) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE таблица index PRIMARY,f2_индекс PRIMARY 4 NULL 56 4.11 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`таблица`@`select#1`) */ `test`.`таблица`.`f1` AS `f1` from `test`.`таблица` where `test`.`таблица`.`f1` > 30 and `test`.`таблица`.`f1` < 33
|
||||
# Turn off range access for PRIMARY & f2_индекс keys
|
||||
# Should use index access
|
||||
EXPLAIN EXTENDED
|
||||
SELECT /*+ NO_RANGE_OPTIMIZATION(таблица PRIMARY) NO_RANGE_OPTIMIZATION(таблица f2_индекс) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE таблица index PRIMARY,f2_индекс PRIMARY 4 NULL 56 4.11 Using where; Using index
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`таблица`@`select#1` `PRIMARY`) NO_RANGE_OPTIMIZATION(`таблица`@`select#1` `f2_индекс`) */ `test`.`таблица`.`f1` AS `f1` from `test`.`таблица` where `test`.`таблица`.`f1` > 30 and `test`.`таблица`.`f1` < 33
|
||||
DROP TABLE таблица;
|
||||
# NO_ICP hint testing
|
||||
set optimizer_switch='index_condition_pushdown=on';
|
||||
CREATE TABLE t4 (x INT, y INT, KEY x_idx(x), KEY y_idx(y));
|
||||
@@ -131,6 +213,15 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_ICP(`t5`@`QB1` `x_idx`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0)
|
||||
# Cyrillic query block name
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_ICP(t5@блок1 x_idx) */ * FROM
|
||||
(SELECT /*+ QB_NAME(блок1) */ t4.x, t5.y FROM t4, t4 t5
|
||||
WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0) AS TD;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ref y_idx y_idx 5 const 1 100.00
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select /*+ NO_ICP(`t5`@`блок1` `x_idx`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0)
|
||||
# Expected warning for z_idx key, unresolved name.
|
||||
EXPLAIN EXTENDED SELECT * FROM
|
||||
(SELECT /*+ NO_ICP(t5 y_idx, x_idx, z_idx) */ t4.x, t5.y FROM t4, t4 t5
|
||||
@@ -299,7 +390,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t13 hash_ALL a #hash#a 5 test.t12.a 1000 0.10 Using where; Using join buffer (flat, BNLH join)
|
||||
Warnings:
|
||||
Note 1003 select /*+ QB_NAME(`QB1`) NO_BKA(`t13`@`QB1`) */ `test`.`t12`.`a` AS `a`,`test`.`t12`.`b` AS `b`,`test`.`t13`.`a` AS `a`,`test`.`t13`.`b` AS `b`,`test`.`t13`.`c` AS `c`,`test`.`t13`.`filler` AS `filler` from `test`.`t12` join `test`.`t13` where `test`.`t13`.`a` = `test`.`t12`.`a` and `test`.`t13`.`b` + 1 <= `test`.`t13`.`b` + 1
|
||||
# UPDATE|DELETE|INSERT hint testing
|
||||
# UPDATE|DELETE|INSERT|REPLACE hint testing
|
||||
EXPLAIN EXTENDED UPDATE t3
|
||||
SET f3 = 'mnbv' WHERE f1 > 30 AND f1 < 33 AND (t3.f1, t3.f2, t3.f3) IN
|
||||
(SELECT t2.f1, t2.f2, t2.f3 FROM t1,t2 WHERE t1.f1=t2.f1 AND
|
||||
@@ -390,13 +481,48 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 (insert into `test`.`t3`(f1,f2,f3) select /*+ QB_NAME(`qb1`) NO_ICP(`t5`@`qb1` `x_idx`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y`,'filler' AS `filler` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0))
|
||||
# Make sure ICP is expected to be used when there are no hints
|
||||
EXPLAIN EXTENDED REPLACE INTO t3(f1, f2, f3)
|
||||
(SELECT t4.x, t5.y, 'filler' FROM t4, t4 t5 WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ref y_idx y_idx 5 const 1 100.00
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using index condition; Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 (replace into `test`.`t3`(f1,f2,f3) select `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y`,'filler' AS `filler` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0))
|
||||
# Turn off ICP. ICP should not be used.
|
||||
EXPLAIN EXTENDED REPLACE INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ NO_ICP(t5) */t4.x, t5.y, 'filler' FROM t4, t4 t5
|
||||
WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ref y_idx y_idx 5 const 1 100.00
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 (replace into `test`.`t3`(f1,f2,f3) select /*+ NO_ICP(`t5`@`select#2`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y`,'filler' AS `filler` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0))
|
||||
# Turn off ICP for a particular table
|
||||
EXPLAIN EXTENDED REPLACE /*+ NO_ICP(t5@QB1) */ INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ 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);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ref y_idx y_idx 5 const 1 100.00
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 (replace into `test`.`t3`(f1,f2,f3) select /*+ QB_NAME(`qb1`) NO_ICP(`t5`@`qb1`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y`,'filler' AS `filler` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0))
|
||||
# Turn off ICP for a particular table and a key
|
||||
EXPLAIN EXTENDED REPLACE /*+ NO_ICP(t5@QB1 x_idx) */ INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ 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);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ref y_idx y_idx 5 const 1 100.00
|
||||
1 SIMPLE t5 range x_idx x_idx 5 NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 (replace into `test`.`t3`(f1,f2,f3) select /*+ QB_NAME(`qb1`) NO_ICP(`t5`@`qb1` `x_idx`) */ `test`.`t4`.`x` AS `x`,`test`.`t5`.`y` AS `y`,'filler' AS `filler` from `test`.`t4` join `test`.`t4` `t5` where `test`.`t4`.`y` = 8 and `test`.`t5`.`x` between 7 and <cache>(8 + 0))
|
||||
# Misc tests
|
||||
# Should issue warning
|
||||
EXPLAIN EXTENDED SELECT /*+ QB_NAME(qb1) QB_NAME(qb1 ) */ * FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 28 100.00
|
||||
Warnings:
|
||||
Warning 4197 Hint QB_NAME(`qb1`) is ignored as conflicting/duplicated
|
||||
Warning 4202 Hint QB_NAME(`qb1`) is ignored as conflicting/duplicated
|
||||
Note 1003 select /*+ QB_NAME(`qb1`) */ `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t2`
|
||||
# Should issue warning
|
||||
EXPLAIN EXTENDED SELECT /*+ BKA(@qb1) QB_NAME(qb1) */ t2.f1, t2.f2, t2.f3 FROM t1,t2
|
||||
@@ -462,7 +588,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
Warnings:
|
||||
Warning 1064 Optimizer hint syntax error near 't3@qb1) */ f2 FROM
|
||||
(SELECT /*+ QB_NAME(qb1) */ f2, f3, f1 FROM t3 WHERE f1 > ...' at line 1
|
||||
Note 1003 select `test`.`t3`.`f2` AS `f2` from `test`.`t3` where `test`.`t3`.`f3` = 'poiu' and `test`.`t3`.`f1` > 2 and `test`.`t3`.`f1` > 2
|
||||
Note 1003 select `test`.`t3`.`f2` AS `f2` from `test`.`t3` where `test`.`t3`.`f1` > 2 and `test`.`t3`.`f3` = 'poiu' and `test`.`t3`.`f1` > 2
|
||||
# Check illegal syntax
|
||||
EXPLAIN EXTENDED SELECT * FROM
|
||||
(SELECT /*+ QB_NAME(qb1) BKA(@qb1 t1@qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt;
|
||||
@@ -471,7 +597,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 28 100.00 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE t3 index NULL PRIMARY 4 NULL 56 100.00 Using index; Using join buffer (incremental, BNL join)
|
||||
Warnings:
|
||||
Warning 1064 Optimizer hint syntax error near 'qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt' at line 2
|
||||
Warning 1064 Optimizer hint syntax error near '@qb1, t2@qb1, t3) */ t2.f1, t2.f2, t2.f3 FROM t1,t2,t3) tt' at line 2
|
||||
Note 1003 select `test`.`t2`.`f1` AS `f1`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3` from `test`.`t1` join `test`.`t2` join `test`.`t3`
|
||||
# Check '@qb_name table_name' syntax
|
||||
EXPLAIN EXTENDED SELECT /*+ BKA(@qb1 t13) */ * FROM (SELECT /*+ QB_NAME(QB1) */ t12.a, t13.b FROM t12, t13
|
||||
@@ -831,7 +957,7 @@ CREATE PROCEDURE p() SELECT /*+ NO_MRR(t1) */ * FROM t1 WHERE f2 <= 3 AND 3 <= f
|
||||
SHOW CREATE PROCEDURE p;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
p STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()
|
||||
SELECT /*+ NO_MRR(t1) */ * FROM t1 WHERE f2 <= 3 AND 3 <= f3 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
SELECT /*+ NO_MRR(t1) */ * FROM t1 WHERE f2 <= 3 AND 3 <= f3 utf8mb4 utf8mb4_uca1400_ai_ci utf8mb4_uca1400_ai_ci
|
||||
FLUSH STATUS;
|
||||
CALL p();
|
||||
f1 f2 f3
|
||||
@@ -1059,7 +1185,6 @@ Warning 1064 Optimizer hint syntax error near ') */ 1 UNION SELECT 1' at line 1
|
||||
1
|
||||
Warnings:
|
||||
Warning 1064 Optimizer hint syntax error near ') */ 1) UNION (SELECT 1)' at line 1
|
||||
# OLEGS: this one does not issue a warning although should:
|
||||
((SELECT /* + NO_ICP() */ 1));
|
||||
1
|
||||
1
|
||||
@@ -1099,7 +1224,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select /*+ QB_NAME(`qb1`) */ 1 AS `1` union /* select#2 */ select 1 AS `1`
|
||||
Note 1003 /* select#1 */ select /*+ QB_NAME(`qb1`) */ 1 AS `1` union /* select#2 */ select /*+ QB_NAME(`qb2`) */ 1 AS `1`
|
||||
EXPLAIN EXTENDED (SELECT /*+ QB_NAME(qb1) */ 1) UNION (SELECT /*+ QB_NAME(qb2) */ 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
@@ -1152,39 +1277,39 @@ CREATE TABLE ` quoted name test` (i INT);
|
||||
SELECT /*+ BKA(` quoted name test`) */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4199 Unresolved name ` quoted name test`@`select#1` for BKA hint
|
||||
Warning 4204 Unresolved table name ` quoted name test`@`select#1` for BKA hint
|
||||
SELECT /*+ BKA(` quoted name test`@`select#1`) */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4198 Query block name `select#1` is not found for BKA hint
|
||||
Warning 4203 Query block name `select#1` is not found for BKA hint
|
||||
DROP TABLE ` quoted name test`;
|
||||
SET SQL_MODE = 'ANSI_QUOTES';
|
||||
CREATE TABLE " quoted name test" (i INT);
|
||||
SELECT /*+ BKA(" quoted name test") */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4199 Unresolved name " quoted name test"@"select#1" for BKA hint
|
||||
Warning 4204 Unresolved table name " quoted name test"@"select#1" for BKA hint
|
||||
SELECT /*+ BKA(" quoted name test"@"select#1") */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4198 Query block name "select#1" is not found for BKA hint
|
||||
Warning 4203 Query block name "select#1" is not found for BKA hint
|
||||
CREATE TABLE `test1``test2``` (i INT);
|
||||
SELECT /*+ BKA(`test1``test2```) */ 1;
|
||||
1
|
||||
1
|
||||
Warnings:
|
||||
Warning 4199 Unresolved name "test1`test2`"@"select#1" for BKA hint
|
||||
Warning 4204 Unresolved table name "test1`test2`"@"select#1" for BKA hint
|
||||
SELECT /*+ BKA("test1""test2""") */ 1;
|
||||
1
|
||||
1
|
||||
Warnings:
|
||||
Warning 4199 Unresolved name "test1""test2"""@"select#1" for BKA hint
|
||||
Warning 4204 Unresolved table name "test1""test2"""@"select#1" for BKA hint
|
||||
SET SQL_MODE = '';
|
||||
# should warn:
|
||||
SELECT /*+ BKA(" quoted name test") */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4204 Unresolved table name `" quoted name test"`@`select#1` for BKA hint
|
||||
Warning 4204 Unresolved table name ` quoted name test`@`select#1` for BKA hint
|
||||
DROP TABLE ` quoted name test`;
|
||||
DROP TABLE `test1``test2```;
|
||||
# Valid hints, no warning:
|
||||
@@ -1238,7 +1363,7 @@ CREATE TABLE таблица (i INT);
|
||||
SELECT /*+ BKA(`таблица`) */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4199 Unresolved name `таблица`@`select#1` for BKA hint
|
||||
Warning 4204 Unresolved table name `таблица`@`select#1` for BKA hint
|
||||
SELECT /*+ BKA(таблица) */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
@@ -1250,7 +1375,7 @@ Warning 4203 Query block name `таблица` is not found for BKA hint
|
||||
SELECT /*+ NO_ICP(`\D1`) */ 1 FROM t1;
|
||||
1
|
||||
Warnings:
|
||||
Warning 4199 Unresolved name `\D1`@`select#1` for NO_ICP hint
|
||||
Warning 4204 Unresolved table name `\D1`@`select#1` for NO_ICP hint
|
||||
DROP TABLE таблица;
|
||||
|
||||
# derived tables and other subqueries:
|
||||
|
@@ -1,6 +1,22 @@
|
||||
--echo # WL#8017 Infrastructure for Optimizer Hints
|
||||
--enable_prepare_warnings
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
--echo # Testing that index names in hints are accent sensitive case insensitive
|
||||
CREATE TABLE t1 (a INT, ä INT, INDEX idx_a(a), INDEX idx_ä(ä));
|
||||
INSERT INTO t1 VALUES (1,1),(2,2);
|
||||
SELECT /*+ NO_MRR(t1 idx_a) */ a FROM t1;
|
||||
SELECT /*+ NO_MRR(t1 idx_A) */ a FROM t1;
|
||||
SELECT /*+ NO_MRR(t1 idx_å) */ a FROM t1;
|
||||
SELECT /*+ NO_MRR(t1 idx_a, idx_å, idx_A) */ a FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Testing that query block names are accent sensitive case insensitive
|
||||
CREATE TABLE t1 (a INT);
|
||||
SELECT /*+ QB_NAME(a) BKA(t1@a) BKA(t1@A) */ * FROM t1;
|
||||
SELECT /*+ QB_NAME(a) BKA(t1@a) BKA(t1@å) */ * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1(f1 INT, f2 INT);
|
||||
INSERT INTO t1 VALUES
|
||||
(1,1),(2,2),(3,3);
|
||||
@@ -31,7 +47,6 @@ ANALYZE TABLE t1;
|
||||
ANALYZE TABLE t2;
|
||||
ANALYZE TABLE t3;
|
||||
|
||||
|
||||
--echo # NO_RANGE_OPTIMIZATION hint testing
|
||||
set optimizer_switch=default;
|
||||
|
||||
@@ -50,16 +65,44 @@ SHOW STATUS LIKE 'handler_read%';
|
||||
EXPLAIN EXTENDED SELECT f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for PRIMARY key
|
||||
--echo # Should use range access by f2_idx key
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for PRIMARY & f2_idx keys
|
||||
--echo # Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for all keys
|
||||
--echo # Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for PRIMARY & f2_idx keys
|
||||
--echo # Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) NO_RANGE_OPTIMIZATION(t3 f2_idx) */ f1 FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY) NO_RANGE_OPTIMIZATION(t3 f2_idx) */ f1
|
||||
FROM t3 WHERE f1 > 30 AND f1 < 33;
|
||||
|
||||
--echo # Create a clone of t3 with cyrillic names
|
||||
CREATE TABLE таблица (f1 INT NOT NULL, поле2 INT, поле3 VARCHAR(32),
|
||||
PRIMARY KEY(f1), KEY f2_индекс(f1), KEY f3_индекс(поле3))
|
||||
AS SELECT * FROM t3;
|
||||
ANALYZE TABLE таблица;
|
||||
--echo # Turn off range access for PRIMARY key
|
||||
--echo # Should use range access by f2_индекс key
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(таблица PRIMARY) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for PRIMARY & f2_индекс keys
|
||||
--echo # Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(таблица PRIMARY, f2_индекс) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for all keys
|
||||
--echo # Should use index access
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_RANGE_OPTIMIZATION(таблица) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
--echo # Turn off range access for PRIMARY & f2_индекс keys
|
||||
--echo # Should use index access
|
||||
EXPLAIN EXTENDED
|
||||
SELECT /*+ NO_RANGE_OPTIMIZATION(таблица PRIMARY) NO_RANGE_OPTIMIZATION(таблица f2_индекс) */ f1
|
||||
FROM таблица WHERE f1 > 30 AND f1 < 33;
|
||||
DROP TABLE таблица;
|
||||
|
||||
--echo # NO_ICP hint testing
|
||||
set optimizer_switch='index_condition_pushdown=on';
|
||||
@@ -79,6 +122,12 @@ EXPLAIN EXTENDED SELECT /*+ NO_ICP(t5@qb1 x_idx) */ * FROM
|
||||
(SELECT /*+ QB_NAME(QB1) */ t4.x, t5.y FROM t4, t4 t5
|
||||
WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0) AS TD;
|
||||
|
||||
--echo # Cyrillic query block name
|
||||
EXPLAIN EXTENDED SELECT /*+ NO_ICP(t5@блок1 x_idx) */ * FROM
|
||||
(SELECT /*+ QB_NAME(блок1) */ t4.x, t5.y FROM t4, t4 t5
|
||||
WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0) AS TD;
|
||||
|
||||
|
||||
--echo # Expected warning for z_idx key, unresolved name.
|
||||
EXPLAIN EXTENDED SELECT * FROM
|
||||
(SELECT /*+ NO_ICP(t5 y_idx, x_idx, z_idx) */ t4.x, t5.y FROM t4, t4 t5
|
||||
@@ -157,7 +206,7 @@ EXPLAIN EXTENDED SELECT /*+ NO_BKA(t12) */ * FROM t12, t13
|
||||
EXPLAIN EXTENDED SELECT /*+ QB_NAME(QB1) NO_BKA(t13@QB1) */ * FROM t12, t13
|
||||
WHERE t12.a=t13.a AND (t13.b+1 <= t13.b+1);
|
||||
|
||||
--echo # UPDATE|DELETE|INSERT hint testing
|
||||
--echo # UPDATE|DELETE|INSERT|REPLACE hint testing
|
||||
EXPLAIN EXTENDED UPDATE t3
|
||||
SET f3 = 'mnbv' WHERE f1 > 30 AND f1 < 33 AND (t3.f1, t3.f2, t3.f3) IN
|
||||
(SELECT t2.f1, t2.f2, t2.f3 FROM t1,t2 WHERE t1.f1=t2.f1 AND
|
||||
@@ -207,6 +256,25 @@ EXPLAIN EXTENDED INSERT /*+ NO_ICP(t5@QB1 x_idx) */ INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ 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
|
||||
EXPLAIN EXTENDED REPLACE INTO t3(f1, f2, f3)
|
||||
(SELECT t4.x, t5.y, 'filler' FROM t4, t4 t5 WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0);
|
||||
|
||||
--echo # Turn off ICP. ICP should not be used.
|
||||
EXPLAIN EXTENDED REPLACE INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ NO_ICP(t5) */t4.x, t5.y, 'filler' FROM t4, t4 t5
|
||||
WHERE t4.y = 8 AND t5.x BETWEEN 7 AND t4.y+0);
|
||||
|
||||
--echo # Turn off ICP for a particular table
|
||||
EXPLAIN EXTENDED REPLACE /*+ NO_ICP(t5@QB1) */ INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ 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 # Turn off ICP for a particular table and a key
|
||||
EXPLAIN EXTENDED REPLACE /*+ NO_ICP(t5@QB1 x_idx) */ INTO t3(f1, f2, f3)
|
||||
(SELECT /*+ 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 # Misc tests
|
||||
|
||||
--echo # Should issue warning
|
||||
@@ -475,7 +543,6 @@ SELECT /*+ NO_ICP ( ) */ 1;
|
||||
SELECT /*+ NO_ICP() */ 1 UNION SELECT 1;
|
||||
(SELECT /*+ NO_ICP() */ 1) UNION (SELECT 1);
|
||||
|
||||
--echo # OLEGS: this one does not issue a warning although should:
|
||||
((SELECT /* + NO_ICP() */ 1));
|
||||
|
||||
UPDATE /*+ NO_ICP() */ t1 SET i = 10;
|
||||
|
@@ -895,7 +895,7 @@ CREATE TABLE t (
|
||||
|
||||
INSERT INTO t(a,b) VALUES(1,'cccc');
|
||||
let $query=
|
||||
SELECT /*+ bka() */ 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
SELECT 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
WHERE b.b>c.a;
|
||||
eval EXPLAIN $query;
|
||||
eval $query;
|
||||
@@ -1022,13 +1022,12 @@ VALUES (1, 'j'), (2, 'c'), (0, 'a');
|
||||
|
||||
ANALYZE TABLE t1, t2, t3, t4;
|
||||
|
||||
# Hint is added to avoid materialization of the subquery
|
||||
let query=
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1049,13 +1048,12 @@ if ($support_virtual_index)
|
||||
ALTER TABLE t3 ADD INDEX v_idx2 (i2_key, i1);
|
||||
}
|
||||
|
||||
# Hint is added to avoid materialization of the subquery
|
||||
let query=
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1079,11 +1077,11 @@ ALTER TABLE t3 DROP INDEX v_idx;
|
||||
|
||||
# Hint is added to avoid materialization of the subquery
|
||||
let query=
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1117,11 +1115,11 @@ VALUES (10,1), (11,1), (12,1), (13,1), (14,1),(15,1), (16,1),(17,1), (18,1),
|
||||
--echo # non-covering.
|
||||
# Hint is added to avoid materialization of the subquery
|
||||
let query=
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1, t3.i1
|
||||
SELECT t1.c1, t2.i1, t3.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1154,11 +1152,11 @@ eval $query;
|
||||
# an extra query condition is added to the subquery.
|
||||
# Hint is added to avoid materialization of the subquery
|
||||
let query=
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o' and t4.i1 < (t2.i1 + 1)
|
||||
)
|
||||
|
@@ -444,7 +444,7 @@ Note 1265 Data truncated for column 'c13' at row 1
|
||||
Note 1265 Data truncated for column 'c11' at row 2
|
||||
Note 1265 Data truncated for column 'c13' at row 2
|
||||
CREATE VIEW view_C AS SELECT * FROM C;
|
||||
SELECT /*+ NO_BNL(t1) */ t1.c13 FROM C AS t2 STRAIGHT_JOIN C AS t1 FORCE INDEX(c13);
|
||||
SELECT t1.c13 FROM C AS t2 STRAIGHT_JOIN C AS t1 FORCE INDEX(c13);
|
||||
c13
|
||||
00:00:00
|
||||
00:00:00
|
||||
|
@@ -555,12 +555,12 @@ c BLOB GENERATED ALWAYS AS (a+b) VIRTUAL,
|
||||
UNIQUE KEY i0008 (a)
|
||||
);
|
||||
INSERT INTO t(a,b) VALUES(1,'cccc');
|
||||
EXPLAIN SELECT /*+ bka() */ 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
EXPLAIN SELECT 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
WHERE b.b>c.a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE b ALL i0008 NULL NULL NULL 1
|
||||
1 SIMPLE c ALL i0008 NULL NULL NULL 1 Range checked for each record (index map: 0x1)
|
||||
SELECT /*+ bka() */ 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
SELECT 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
WHERE b.b>c.a;
|
||||
c
|
||||
Warnings:
|
||||
@@ -689,11 +689,11 @@ test.t3 analyze status Engine-independent statistics collected
|
||||
test.t3 analyze status OK
|
||||
test.t4 analyze status Engine-independent statistics collected
|
||||
test.t4 analyze status OK
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -704,11 +704,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -743,11 +743,11 @@ t 9
|
||||
#
|
||||
# Test 2: Two alternative covering indexes for the range scan
|
||||
#
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -758,11 +758,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -798,11 +798,11 @@ t 9
|
||||
# Test 3: One covering index including the base column for the virtual
|
||||
# column
|
||||
#
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -813,11 +813,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -861,11 +861,11 @@ VALUES (10,1), (11,1), (12,1), (13,1), (14,1),(15,1), (16,1),(17,1), (18,1),
|
||||
(28,1), (29,1);
|
||||
# Change the query to read an extra column (t3.i1) making the index
|
||||
# non-covering.
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1, t3.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1, t3.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -876,11 +876,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1, t3.i1
|
||||
SELECT t1.c1, t2.i1, t3.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -916,11 +916,11 @@ t 9 48
|
||||
# Test 5: Test where the added primary key to secondary indexes is
|
||||
# used after it has been included in the join buffer
|
||||
#
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o' and t4.i1 < (t2.i1 + 1)
|
||||
)
|
||||
@@ -931,11 +931,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.i1 1 Using where
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; End temporary; Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o' and t4.i1 < (t2.i1 + 1)
|
||||
)
|
||||
|
@@ -1174,14 +1174,14 @@ c BLOB GENERATED ALWAYS AS (a+b) VIRTUAL,
|
||||
UNIQUE KEY i0008 (a)
|
||||
);
|
||||
INSERT INTO t(a,b) VALUES(1,'cccc');
|
||||
EXPLAIN SELECT /*+ bka() */ 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
EXPLAIN SELECT 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
WHERE b.b>c.a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'cccc'
|
||||
Warning 1292 Truncated incorrect DECIMAL value: 'cccc'
|
||||
SELECT /*+ bka() */ 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
SELECT 1 AS c FROM t AS b RIGHT JOIN t AS c ON b.a > c.c
|
||||
WHERE b.b>c.a;
|
||||
c
|
||||
Warnings:
|
||||
@@ -1315,11 +1315,11 @@ test.t3 analyze status Engine-independent statistics collected
|
||||
test.t3 analyze status OK
|
||||
test.t4 analyze status Engine-independent statistics collected
|
||||
test.t4 analyze status OK
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1330,11 +1330,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY,v_idx PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1370,11 +1370,11 @@ t 9
|
||||
# Test 2: Two alternative covering indexes for the range scan
|
||||
#
|
||||
ALTER TABLE t3 ADD INDEX v_idx2 (i2_key, i1);
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1385,11 +1385,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY,v_idx,v_idx2 PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1427,11 +1427,11 @@ t 9
|
||||
#
|
||||
# Drop the index with only the virtual column
|
||||
ALTER TABLE t3 DROP INDEX v_idx;
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1442,11 +1442,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY,v_idx2 PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1493,11 +1493,11 @@ VALUES (10,1), (11,1), (12,1), (13,1), (14,1),(15,1), (16,1),(17,1), (18,1),
|
||||
(28,1), (29,1);
|
||||
# Change the query to read an extra column (t3.i1) making the index
|
||||
# non-covering.
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1, t3.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1, t3.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1508,11 +1508,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY,v_idx PRIMARY 4 test.t4.i1 1 Using where; End temporary
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1, t3.i1
|
||||
SELECT t1.c1, t2.i1, t3.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o'
|
||||
)
|
||||
@@ -1548,11 +1548,11 @@ t 9 48
|
||||
# Test 5: Test where the added primary key to secondary indexes is
|
||||
# used after it has been included in the join buffer
|
||||
#
|
||||
EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
EXPLAIN SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o' and t4.i1 < (t2.i1 + 1)
|
||||
)
|
||||
@@ -1563,11 +1563,11 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
|
||||
1 PRIMARY t3 eq_ref PRIMARY,v_idx PRIMARY 4 test.t4.i1 1 Using where
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; End temporary; Using join buffer (flat, BNL join)
|
||||
SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1
|
||||
SELECT t1.c1, t2.i1
|
||||
FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2
|
||||
WHERE ( t3.pk IN
|
||||
(
|
||||
SELECT /*+ QB_NAME(subq1) */ t4.i1
|
||||
SELECT t4.i1
|
||||
FROM t4
|
||||
WHERE t4.c1 < 'o' and t4.i1 < (t2.i1 + 1)
|
||||
)
|
||||
|
@@ -429,7 +429,7 @@ INSERT INTO C (c8,c9) VALUES('1970-01-01',0),('1970-01-01',1);
|
||||
|
||||
CREATE VIEW view_C AS SELECT * FROM C;
|
||||
|
||||
SELECT /*+ NO_BNL(t1) */ t1.c13 FROM C AS t2 STRAIGHT_JOIN C AS t1 FORCE INDEX(c13);
|
||||
SELECT t1.c13 FROM C AS t2 STRAIGHT_JOIN C AS t1 FORCE INDEX(c13);
|
||||
SELECT DISTINCT t1.c13 FROM C AS t1, view_C AS t2;
|
||||
|
||||
DROP TABLE C;
|
||||
|
@@ -469,7 +469,7 @@ id jid val
|
||||
2 1 2
|
||||
2 2 4
|
||||
2 3 6
|
||||
SELECT /*+ JOIN_ORDER(jt, t1) */ id, jt.*
|
||||
SELECT id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt;
|
||||
@@ -480,14 +480,14 @@ id jid val
|
||||
2 1 2
|
||||
2 2 4
|
||||
2 3 6
|
||||
EXPLAIN SELECT /*+ JOIN_ORDER(jt, t1) */ id, jt.*
|
||||
EXPLAIN SELECT id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
|
||||
1 SIMPLE jt ALL NULL NULL NULL NULL 40 Table function: json_table
|
||||
SELECT /*+ JOIN_ORDER(t2,jt) */ t1.id, t2.id, jt.*
|
||||
SELECT t1.id, t2.id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(t1.jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt,
|
||||
@@ -514,7 +514,7 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE jt ALL NULL NULL NULL NULL 40 Table function: json_table
|
||||
EXPLAIN SELECT /*+ JOIN_ORDER(t2,jt) */ t1.id, t2.id, jt.*
|
||||
EXPLAIN SELECT t1.id, t2.id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(t1.jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt,
|
||||
|
@@ -379,18 +379,18 @@ INSERT INTO t1 values (1, '[1,3,5]'),(2,'[2,4,6]');
|
||||
SELECT id, jt.* FROM t1,
|
||||
JSON_TABLE(jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt;
|
||||
SELECT /*+ JOIN_ORDER(jt, t1) */ id, jt.*
|
||||
SELECT id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt;
|
||||
|
||||
EXPLAIN SELECT /*+ JOIN_ORDER(jt, t1) */ id, jt.*
|
||||
EXPLAIN SELECT id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt;
|
||||
|
||||
--sorted_result
|
||||
SELECT /*+ JOIN_ORDER(t2,jt) */ t1.id, t2.id, jt.*
|
||||
SELECT t1.id, t2.id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(t1.jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt,
|
||||
@@ -402,7 +402,7 @@ EXPLAIN SELECT t1.id, t2.id, jt.*
|
||||
val INT PATH '$')) AS jt,
|
||||
t1 AS t2;
|
||||
|
||||
EXPLAIN SELECT /*+ JOIN_ORDER(t2,jt) */ t1.id, t2.id, jt.*
|
||||
EXPLAIN SELECT t1.id, t2.id, jt.*
|
||||
FROM t1,
|
||||
JSON_TABLE(t1.jd, '$[*]' COLUMNS (jid FOR ORDINALITY,
|
||||
val INT PATH '$')) AS jt,
|
||||
|
162
sql/opt_hints.cc
162
sql/opt_hints.cc
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2024, 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
|
||||
@@ -33,13 +34,13 @@
|
||||
|
||||
struct st_opt_hint_info opt_hint_info[]=
|
||||
{
|
||||
{"BKA", true, true},
|
||||
{"BNL", true, true},
|
||||
{"ICP", true, true},
|
||||
{"MRR", true, true},
|
||||
{"NO_RANGE_OPTIMIZATION", true, true},
|
||||
{"QB_NAME", false, false},
|
||||
{0, 0, 0}
|
||||
{{STRING_WITH_LEN("BKA")}, true, true},
|
||||
{{STRING_WITH_LEN("BNL")}, true, true},
|
||||
{{STRING_WITH_LEN("ICP")}, true, true},
|
||||
{{STRING_WITH_LEN("MRR")}, true, true},
|
||||
{{STRING_WITH_LEN("NO_RANGE_OPTIMIZATION")}, true, true},
|
||||
{{STRING_WITH_LEN("QB_NAME")}, false, false},
|
||||
{null_clex_str, 0, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -49,35 +50,14 @@ struct st_opt_hint_info opt_hint_info[]=
|
||||
|
||||
const LEX_CSTRING sys_qb_prefix= {"select#", 7};
|
||||
|
||||
|
||||
/*
|
||||
Compare LEX_CSTRING objects.
|
||||
|
||||
@param s Pointer to LEX_CSTRING
|
||||
@param t Pointer to LEX_CSTRING
|
||||
|
||||
@return 0 if strings are equal
|
||||
1 if s is greater
|
||||
-1 if t is greater
|
||||
*/
|
||||
|
||||
static int cmp_lex_string(const LEX_CSTRING *s,
|
||||
const LEX_CSTRING *t)
|
||||
{
|
||||
return system_charset_info->
|
||||
coll->strnncollsp(system_charset_info,
|
||||
(uchar *) s->str, s->length,
|
||||
(uchar *) t->str, t->length);
|
||||
}
|
||||
|
||||
|
||||
static const Lex_ident_sys null_ident_sys;
|
||||
|
||||
static void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
static
|
||||
void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
bool hint_state,
|
||||
const Lex_ident_sys *qb_name_arg,
|
||||
const Lex_ident_sys *table_name_arg,
|
||||
const Lex_ident_sys *key_name_arg/*, PT_hint *hint*/)
|
||||
const Lex_ident_sys *key_name_arg)
|
||||
{
|
||||
String str;
|
||||
|
||||
@@ -107,7 +87,14 @@ static void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
/* Append QB name */
|
||||
if (qb_name_arg && qb_name_arg->length > 0)
|
||||
{
|
||||
str.append(STRING_WITH_LEN("@"));
|
||||
if (hint_type != QB_NAME_HINT_ENUM)
|
||||
{
|
||||
/*
|
||||
Add the delimiter for warnings like "Hint NO_ICP(`t1`@`q1` is ignored".
|
||||
No need for the delimiter for warnings "Hint QB_NAME(qb1) is ignored"
|
||||
*/
|
||||
str.append(STRING_WITH_LEN("@"));
|
||||
}
|
||||
append_identifier(thd, &str, qb_name_arg->str, qb_name_arg->length);
|
||||
}
|
||||
|
||||
@@ -118,16 +105,6 @@ static void print_warn(THD *thd, uint err_code, opt_hints_enum hint_type,
|
||||
append_identifier(thd, &str, key_name_arg->str, key_name_arg->length);
|
||||
}
|
||||
|
||||
/* Append additional hint arguments if they exist */
|
||||
// OLEGS: todo
|
||||
// if (hint)
|
||||
// {
|
||||
// if (qb_name_arg || table_name_arg || key_name_arg)
|
||||
// str.append(' ');
|
||||
|
||||
// hint->append_args(thd, &str);
|
||||
// }
|
||||
|
||||
str.append(')');
|
||||
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
|
||||
@@ -150,7 +127,10 @@ static Opt_hints_global *get_global_hints(Parse_context *pc)
|
||||
LEX *lex= pc->thd->lex;
|
||||
|
||||
if (!lex->opt_hints_global)
|
||||
lex->opt_hints_global= new Opt_hints_global(pc->thd->mem_root);
|
||||
{
|
||||
lex->opt_hints_global= new (pc->thd->mem_root)
|
||||
Opt_hints_global(pc->thd->mem_root);
|
||||
}
|
||||
if (lex->opt_hints_global)
|
||||
lex->opt_hints_global->set_resolved();
|
||||
return lex->opt_hints_global;
|
||||
@@ -166,8 +146,8 @@ static Opt_hints_qb *get_qb_hints(Parse_context *pc)
|
||||
if (global_hints == NULL)
|
||||
return NULL;
|
||||
|
||||
Opt_hints_qb *qb= new Opt_hints_qb(global_hints, pc->thd->mem_root,
|
||||
pc->select->select_number);
|
||||
Opt_hints_qb *qb= new (pc->thd->mem_root)
|
||||
Opt_hints_qb(global_hints, pc->thd->mem_root, pc->select->select_number);
|
||||
if (qb)
|
||||
{
|
||||
global_hints->register_child(qb);
|
||||
@@ -182,8 +162,9 @@ static Opt_hints_qb *get_qb_hints(Parse_context *pc)
|
||||
if the query block is not found.
|
||||
|
||||
@param pc pointer to Parse_context object
|
||||
@param table_name query block name
|
||||
@param hint processed hint // OLEGS: amend this
|
||||
@param qb_name query block name
|
||||
@param hint_type the type of the hint from opt_hints_enum
|
||||
@param hint_state true: hint enables a feature; false: disables it
|
||||
|
||||
@return pointer to Opt_hints_table object if found,
|
||||
NULL otherwise
|
||||
@@ -229,7 +210,8 @@ static Opt_hints_table *get_table_hints(Parse_context *pc,
|
||||
static_cast<Opt_hints_table *> (qb->find_by_name(table_name));
|
||||
if (!tab)
|
||||
{
|
||||
tab= new Opt_hints_table(table_name, qb, pc->thd->mem_root);
|
||||
tab= new (pc->thd->mem_root)
|
||||
Opt_hints_table(table_name, qb, pc->thd->mem_root);
|
||||
qb->register_child(tab);
|
||||
}
|
||||
|
||||
@@ -237,12 +219,10 @@ static Opt_hints_table *get_table_hints(Parse_context *pc,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Opt_hints::get_switch(opt_hints_enum type_arg) const
|
||||
{
|
||||
if (is_specified(type_arg))
|
||||
return hints_map.switch_on(type_arg);
|
||||
return hints_map.is_switched_on(type_arg);
|
||||
|
||||
if (opt_hint_info[type_arg].check_upper_lvl)
|
||||
return parent->get_switch(type_arg);
|
||||
@@ -255,8 +235,9 @@ Opt_hints* Opt_hints::find_by_name(const LEX_CSTRING &name_arg) const
|
||||
{
|
||||
for (uint i= 0; i < child_array.size(); i++)
|
||||
{
|
||||
const LEX_CSTRING *name= child_array[i]->get_name();
|
||||
if (name && !cmp_lex_string(name, &name_arg))
|
||||
const LEX_CSTRING name= child_array[i]->get_name();
|
||||
CHARSET_INFO *cs= child_array[i]->charset_info();
|
||||
if (name.str && !cs->strnncollsp(name, name_arg))
|
||||
return child_array[i];
|
||||
}
|
||||
return NULL;
|
||||
@@ -272,9 +253,6 @@ void Opt_hints::print(THD *thd, String *str)
|
||||
append_hint_type(str, static_cast<opt_hints_enum>(i));
|
||||
str->append(STRING_WITH_LEN("("));
|
||||
append_name(thd, str);
|
||||
// OLEGS:
|
||||
//if (!opt_hint_info[i].switch_hint)
|
||||
// get_complex_hints(i)->append_args(thd, str);
|
||||
str->append(STRING_WITH_LEN(") "));
|
||||
}
|
||||
}
|
||||
@@ -286,10 +264,9 @@ void Opt_hints::print(THD *thd, String *str)
|
||||
|
||||
void Opt_hints::append_hint_type(String *str, opt_hints_enum type)
|
||||
{
|
||||
const char* hint_name= opt_hint_info[type].hint_name;
|
||||
if(!hints_map.switch_on(type))
|
||||
if(!hints_map.is_switched_on(type))
|
||||
str->append(STRING_WITH_LEN("NO_"));
|
||||
str->append(hint_name);
|
||||
str->append(opt_hint_info[type].hint_name);
|
||||
}
|
||||
|
||||
|
||||
@@ -327,13 +304,6 @@ void Opt_hints::check_unresolved(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
PT_hint *Opt_hints_global::get_complex_hints(uint type)
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Opt_hints_qb::Opt_hints_qb(Opt_hints *opt_hints_arg,
|
||||
MEM_ROOT *mem_root_arg,
|
||||
uint select_number_arg)
|
||||
@@ -360,7 +330,11 @@ Opt_hints_table *Opt_hints_qb::adjust_table_hints(TABLE *table,
|
||||
return tab;
|
||||
}
|
||||
|
||||
/*
|
||||
@brief
|
||||
For each index IDX, put its hints into keyinfo_array[IDX]
|
||||
|
||||
*/
|
||||
void Opt_hints_table::adjust_key_hints(TABLE *table)
|
||||
{
|
||||
set_resolved();
|
||||
@@ -370,7 +344,7 @@ void Opt_hints_table::adjust_key_hints(TABLE *table)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure that adjustement is called only once. */
|
||||
/* Make sure that adjustment is called only once. */
|
||||
DBUG_ASSERT(keyinfo_array.size() == 0);
|
||||
keyinfo_array.resize(table->s->keys, NULL);
|
||||
|
||||
@@ -380,7 +354,7 @@ void Opt_hints_table::adjust_key_hints(TABLE *table)
|
||||
KEY *key_info= table->key_info;
|
||||
for (uint j= 0 ; j < table->s->keys ; j++, key_info++)
|
||||
{
|
||||
if (!cmp_lex_string((*hint)->get_name(), &key_info->name))
|
||||
if (key_info->name.streq((*hint)->get_name()))
|
||||
{
|
||||
(*hint)->set_resolved();
|
||||
keyinfo_array[j]= static_cast<Opt_hints_key *>(*hint);
|
||||
@@ -445,6 +419,14 @@ static bool get_hint_state(Opt_hints *hint,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief
|
||||
Check whether a given optimization is enabled for table.keyno.
|
||||
|
||||
@detail
|
||||
First check if a hint is present, then check optimizer_switch
|
||||
*/
|
||||
|
||||
bool hint_key_state(const THD *thd, const TABLE *table,
|
||||
uint keyno, opt_hints_enum type_arg,
|
||||
uint optimizer_switch)
|
||||
@@ -543,7 +525,7 @@ bool Optimizer_hint_parser::Table_level_hint::resolve(Parse_context *pc) const
|
||||
// e.g. BKA(@qb1)
|
||||
if (qb->set_switch(hint_state, hint_type, false))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&qb_name_sys, NULL, NULL/*, this*/);
|
||||
&qb_name_sys, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -555,10 +537,10 @@ bool Optimizer_hint_parser::Table_level_hint::resolve(Parse_context *pc) const
|
||||
const Lex_ident_sys table_name_sys= table.to_ident_sys(pc->thd);
|
||||
Opt_hints_table *tab= get_table_hints(pc, table_name_sys, qb);
|
||||
if (!tab)
|
||||
return true; // OLEGS: why no warning?
|
||||
return true;
|
||||
if (tab->set_switch(hint_state, hint_type, true))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&qb_name_sys, &table_name_sys, NULL/*, this*/);
|
||||
&qb_name_sys, &table_name_sys, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -575,7 +557,7 @@ bool Optimizer_hint_parser::Table_level_hint::resolve(Parse_context *pc) const
|
||||
// e.g. BKA()
|
||||
if (qb->set_switch(hint_state, hint_type, false))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&null_ident_sys, NULL, NULL/*, this*/);
|
||||
&null_ident_sys, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
for (const Table_name &table : table_name_list)
|
||||
@@ -584,10 +566,10 @@ bool Optimizer_hint_parser::Table_level_hint::resolve(Parse_context *pc) const
|
||||
const Lex_ident_sys table_name_sys= table.to_ident_sys(pc->thd);
|
||||
Opt_hints_table *tab= get_table_hints(pc, table_name_sys, qb);
|
||||
if (!tab)
|
||||
return true; // OLEGS: no warning?
|
||||
return true;
|
||||
if (tab->set_switch(hint_state, hint_type, true))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&null_ident_sys, &table_name_sys, NULL/*, this*/);
|
||||
&null_ident_sys, &table_name_sys, NULL);
|
||||
}
|
||||
|
||||
for (const Hint_param_table &table : opt_hint_param_table_list)
|
||||
@@ -598,16 +580,14 @@ bool Optimizer_hint_parser::Table_level_hint::resolve(Parse_context *pc) const
|
||||
Opt_hints_qb *qb= find_qb_hints(pc, qb_name_sys, hint_type, hint_state);
|
||||
if (qb == NULL)
|
||||
return false;
|
||||
// OLEGS: todo
|
||||
const Lex_ident_sys table_name_sys= table.Table_name::
|
||||
to_ident_sys(pc->thd);
|
||||
Opt_hints_table *tab= get_table_hints(pc, table_name_sys, qb);
|
||||
if (!tab)
|
||||
return true; // OLEGS: why no warning?
|
||||
|
||||
return true;
|
||||
if (tab->set_switch(hint_state, hint_type, true))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&qb_name_sys, &table_name_sys, NULL/*, this*/);
|
||||
&qb_name_sys, &table_name_sys, NULL);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -654,13 +634,13 @@ bool Optimizer_hint_parser::Index_level_hint::resolve(Parse_context *pc) const
|
||||
|
||||
Opt_hints_table *tab= get_table_hints(pc, table_name_sys, qb);
|
||||
if (!tab)
|
||||
return true; // OLEGS: why no warning?
|
||||
return true;
|
||||
|
||||
if (is_empty()) // Table level hint
|
||||
{
|
||||
if (tab->set_switch(hint_state, hint_type, false))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&qb_name_sys, &table_name_sys, NULL/*, this*/);
|
||||
&qb_name_sys, &table_name_sys, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -670,13 +650,14 @@ bool Optimizer_hint_parser::Index_level_hint::resolve(Parse_context *pc) const
|
||||
Opt_hints_key *idx= (Opt_hints_key *)tab->find_by_name(index_name_sys);
|
||||
if (!idx)
|
||||
{
|
||||
idx= new Opt_hints_key(index_name_sys, tab, pc->thd->mem_root);
|
||||
idx= new (pc->thd->mem_root)
|
||||
Opt_hints_key(index_name_sys, tab, pc->thd->mem_root);
|
||||
tab->register_child(idx);
|
||||
}
|
||||
|
||||
if (idx->set_switch(hint_state, hint_type, true))
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, hint_type, hint_state,
|
||||
&qb_name_sys, &table_name_sys, &index_name_sys/*, this*/);
|
||||
&qb_name_sys, &table_name_sys, &index_name_sys);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -691,11 +672,11 @@ bool Optimizer_hint_parser::Qb_name_hint::resolve(Parse_context *pc) const
|
||||
|
||||
const Lex_ident_sys qb_name_sys= Query_block_name::to_ident_sys(pc->thd);
|
||||
|
||||
if (qb->get_name() || // QB name is already set
|
||||
if (qb->get_name().str || // QB name is already set
|
||||
qb->get_parent()->find_by_name(qb_name_sys)) // Name is already used
|
||||
{
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, QB_NAME_HINT_ENUM, false,
|
||||
NULL, NULL, NULL/*, this*/);
|
||||
print_warn(pc->thd, ER_WARN_CONFLICTING_HINT, QB_NAME_HINT_ENUM, true,
|
||||
&qb_name_sys, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -712,23 +693,20 @@ bool Optimizer_hint_parser::Hint_list::resolve(Parse_context *pc)
|
||||
List_iterator_fast<Optimizer_hint_parser::Hint> li(*this);
|
||||
while(Optimizer_hint_parser::Hint *hint= li++)
|
||||
{
|
||||
if (const Table_level_hint &table_hint=
|
||||
static_cast<const Table_level_hint &>(*hint))
|
||||
if (const Table_level_hint &table_hint= *hint)
|
||||
{
|
||||
if (table_hint.resolve(pc))
|
||||
return true;
|
||||
}
|
||||
else if (const Index_level_hint &index_hint=
|
||||
static_cast<const Index_level_hint &>(*hint))
|
||||
else if (const Index_level_hint &index_hint= *hint)
|
||||
{
|
||||
if (index_hint.resolve(pc))
|
||||
return true;
|
||||
}
|
||||
else if (const Qb_name_hint &qb_hint=
|
||||
static_cast<const Qb_name_hint &>(*hint))
|
||||
else if (const Qb_name_hint &qb_hint= *hint)
|
||||
{
|
||||
if (qb_hint.resolve(pc))
|
||||
return true; // OLEGS: check this result
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2024, MariaDB plc.
|
||||
|
||||
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
|
||||
@@ -53,7 +54,7 @@ enum opt_hints_enum
|
||||
|
||||
struct st_opt_hint_info
|
||||
{
|
||||
const char* hint_name; // Hint name.
|
||||
LEX_CSTRING hint_name; // Hint name.
|
||||
bool check_upper_lvl; // true if upper level hint check is needed (for hints
|
||||
// which can be specified on more than one level).
|
||||
bool switch_hint; // true if hint is not complex.
|
||||
@@ -81,7 +82,7 @@ public:
|
||||
Check if hint is specified.
|
||||
|
||||
@param type_arg hint type
|
||||
|
||||
|
||||
@return true if hint is specified,
|
||||
false otherwise
|
||||
*/
|
||||
@@ -111,15 +112,13 @@ public:
|
||||
|
||||
@return switch value.
|
||||
*/
|
||||
bool switch_on(opt_hints_enum type_arg) const
|
||||
bool is_switched_on(opt_hints_enum type_arg) const
|
||||
{
|
||||
return hints.is_set(type_arg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PT_hint;
|
||||
class PT_hint_max_execution_time;
|
||||
class Opt_hints_key;
|
||||
|
||||
|
||||
@@ -129,15 +128,16 @@ class Opt_hints_key;
|
||||
|
||||
Opt_hints_global class is hierarchical structure.
|
||||
It contains information about global hints and also
|
||||
conains array of QUERY BLOCK level objects (Opt_hints_qb class).
|
||||
contains array of QUERY BLOCK level objects (Opt_hints_qb class).
|
||||
Each QUERY BLOCK level object contains array of TABLE level hints
|
||||
(class Opt_hints_table). Each TABLE level hint contains array of
|
||||
KEY lelev hints (Opt_hints_key class).
|
||||
KEY level hints (Opt_hints_key class).
|
||||
Hint information(specified, on|off state) is stored in hints_map object.
|
||||
*/
|
||||
|
||||
class Opt_hints : public Sql_alloc
|
||||
{
|
||||
protected:
|
||||
/*
|
||||
Name of object referred by the hint.
|
||||
This name is empty for global level,
|
||||
@@ -146,6 +146,7 @@ class Opt_hints : public Sql_alloc
|
||||
for key level.
|
||||
*/
|
||||
Lex_ident_sys name;
|
||||
private:
|
||||
/*
|
||||
Parent object. There is no parent for global level,
|
||||
for query block level parent is Opt_hints_global object,
|
||||
@@ -209,9 +210,14 @@ public:
|
||||
*/
|
||||
bool get_switch(opt_hints_enum type_arg) const;
|
||||
|
||||
virtual const LEX_CSTRING *get_name() const
|
||||
virtual CHARSET_INFO *charset_info() const
|
||||
{
|
||||
return name.str ? &name : nullptr;
|
||||
return Lex_ident_column::charset_info();
|
||||
}
|
||||
|
||||
const LEX_CSTRING get_name() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
void set_name(const Lex_ident_sys &name_arg) { name= name_arg; }
|
||||
Opt_hints *get_parent() const { return parent; }
|
||||
@@ -230,25 +236,11 @@ public:
|
||||
child_array.push_back(hint_arg);
|
||||
}
|
||||
|
||||
// OLEGS: remove it if not used
|
||||
/**
|
||||
Returns pointer to complex hint for a given type
|
||||
|
||||
@param type hint type
|
||||
|
||||
@return pointer to complex hint for a given type.
|
||||
*/
|
||||
// virtual PT_hint *get_complex_hints(uint type)
|
||||
// {
|
||||
// DBUG_ASSERT(0);
|
||||
// return NULL; /* error C4716: must return a value*/
|
||||
// };
|
||||
|
||||
/**
|
||||
Find hint among lower-level hint objects.
|
||||
|
||||
@param name_arg hint name
|
||||
|
||||
|
||||
@return hint if found,
|
||||
NULL otherwise
|
||||
*/
|
||||
@@ -303,16 +295,11 @@ class Opt_hints_global : public Opt_hints
|
||||
{
|
||||
|
||||
public:
|
||||
PT_hint_max_execution_time *max_exec_time;
|
||||
|
||||
Opt_hints_global(MEM_ROOT *mem_root_arg)
|
||||
: Opt_hints(Lex_ident_sys(), NULL, mem_root_arg)
|
||||
{
|
||||
max_exec_time= NULL;
|
||||
}
|
||||
{}
|
||||
|
||||
virtual void append_name(THD *thd, String *str) {}
|
||||
virtual PT_hint *get_complex_hints(uint type);
|
||||
virtual void append_name(THD *thd, String *str) override {}
|
||||
};
|
||||
|
||||
|
||||
@@ -334,10 +321,9 @@ public:
|
||||
MEM_ROOT *mem_root_arg,
|
||||
uint select_number_arg);
|
||||
|
||||
const LEX_CSTRING *get_print_name()
|
||||
const LEX_CSTRING get_print_name()
|
||||
{
|
||||
const LEX_CSTRING *str= Opt_hints::get_name();
|
||||
return str ? str : &sys_name;
|
||||
return name.str ? name : sys_name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,10 +334,10 @@ public:
|
||||
*/
|
||||
void append_qb_hint(THD *thd, String *str)
|
||||
{
|
||||
if (get_name())
|
||||
if (name.str)
|
||||
{
|
||||
str->append(STRING_WITH_LEN("QB_NAME("));
|
||||
append_identifier(thd, str, get_name()->str, get_name()->length);
|
||||
append_identifier(thd, str, &name);
|
||||
str->append(STRING_WITH_LEN(") "));
|
||||
}
|
||||
}
|
||||
@@ -361,10 +347,11 @@ public:
|
||||
@param thd pointer to THD object
|
||||
@param str pointer to String object
|
||||
*/
|
||||
virtual void append_name(THD *thd, String *str)
|
||||
virtual void append_name(THD *thd, String *str) override
|
||||
{
|
||||
str->append(STRING_WITH_LEN("@"));
|
||||
append_identifier(thd, str, get_print_name()->str, get_print_name()->length);
|
||||
const LEX_CSTRING print_name= get_print_name();
|
||||
append_identifier(thd, str, &print_name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,15 +386,21 @@ public:
|
||||
keyinfo_array(mem_root_arg)
|
||||
{ }
|
||||
|
||||
CHARSET_INFO *charset_info() const override
|
||||
{
|
||||
return Lex_ident_table::charset_info();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Append table name.
|
||||
|
||||
@param thd pointer to THD object
|
||||
@param str pointer to String object
|
||||
*/
|
||||
virtual void append_name(THD *thd, String *str)
|
||||
virtual void append_name(THD *thd, String *str) override
|
||||
{
|
||||
append_identifier(thd, str, get_name()->str, get_name()->length);
|
||||
append_identifier(thd, str, &name);
|
||||
get_parent()->append_name(thd, str);
|
||||
}
|
||||
/**
|
||||
@@ -445,11 +438,11 @@ public:
|
||||
@param thd pointer to THD object
|
||||
@param str pointer to String object
|
||||
*/
|
||||
virtual void append_name(THD *thd, String *str)
|
||||
virtual void append_name(THD *thd, String *str) override
|
||||
{
|
||||
get_parent()->append_name(thd, str);
|
||||
str->append(' ');
|
||||
append_identifier(thd, str, get_name()->str, get_name()->length);
|
||||
append_identifier(thd, str, &name);
|
||||
}
|
||||
|
||||
virtual uint get_warn_unresolved_code() const override
|
||||
@@ -507,5 +500,4 @@ bool hint_table_state(const THD *thd, const TABLE *table,
|
||||
bool hint_table_state_or_fallback(const THD *thd, const TABLE *table,
|
||||
opt_hints_enum type_arg,
|
||||
bool fallback_value);
|
||||
|
||||
#endif /* OPT_HINTS_INCLUDED */
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "sql_error.h"
|
||||
#include "mysqld_error.h"
|
||||
#include "sql_class.h"
|
||||
#include "sql_show.h"
|
||||
|
||||
|
||||
extern struct st_opt_hint_info opt_hint_info[];
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "lex_ident_sys.h"
|
||||
#include "simple_tokenizer.h"
|
||||
#include "sql_list.h"
|
||||
#include "sql_string.h"
|
||||
#include "simple_parser.h"
|
||||
|
||||
class st_select_lex;
|
||||
@@ -565,7 +566,6 @@ private:
|
||||
{
|
||||
public:
|
||||
using OR3::OR3;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -579,8 +579,6 @@ private:
|
||||
size_t count() const { return elements; }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
class Hint_list: public LIST<PARSER, Hint_list_container,
|
||||
Hint, TokenID::tNULL/*not separated list*/, 1>
|
||||
{
|
||||
@@ -590,6 +588,7 @@ public:
|
||||
bool resolve(Parse_context *pc);
|
||||
};
|
||||
|
||||
public:
|
||||
/*
|
||||
The main rule:
|
||||
hints ::= hint_list EOF
|
||||
@@ -608,10 +607,10 @@ public:
|
||||
instead of including the entire opt_hints_parser.h.
|
||||
(forward declarations of qualified nested classes are not possible in C++)
|
||||
*/
|
||||
class Optimizer_hint_parser_output: public Optimizer_hint_parser::Hint_list
|
||||
class Optimizer_hint_parser_output: public Optimizer_hint_parser::Hints
|
||||
{
|
||||
public:
|
||||
using Hint_list::Hint_list;
|
||||
using Hints::Hints;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -196,7 +196,7 @@ protected:
|
||||
|
||||
|
||||
/*
|
||||
A rule consisting of three other rules in a row:
|
||||
A rule consisting of four other rules in a row:
|
||||
rule ::= rule1 rule2 rule3 rule4
|
||||
*/
|
||||
template<class PARSER, class A, class B, class C, class D>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#define SIMPLE_TOKENIZER_INCLUDED
|
||||
|
||||
|
||||
#include "lex_ident.h"
|
||||
#include "lex_string.h"
|
||||
#include "scan_char.h"
|
||||
|
||||
/**
|
||||
|
@@ -3112,7 +3112,7 @@ void st_select_lex::init_query()
|
||||
pushdown_select= 0;
|
||||
orig_names_of_item_list_elems= 0;
|
||||
opt_hints_qb= 0;
|
||||
parsed_optimizer_hints= 0; // OLEGS: remove if not used
|
||||
parsed_optimizer_hints= 0;
|
||||
}
|
||||
|
||||
void st_select_lex::init_select()
|
||||
@@ -3167,7 +3167,7 @@ void st_select_lex::init_select()
|
||||
orig_names_of_item_list_elems= 0;
|
||||
item_list_usage= MARK_COLUMNS_READ;
|
||||
opt_hints_qb= 0;
|
||||
parsed_optimizer_hints= 0; // OLEGS: remove if not used
|
||||
parsed_optimizer_hints= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -11107,6 +11107,7 @@ bool LEX::parsed_insert_select(SELECT_LEX *first_select)
|
||||
return true;
|
||||
|
||||
// fix "main" select
|
||||
resolve_optimizer_hints_in_last_select();
|
||||
SELECT_LEX *blt __attribute__((unused))= pop_select();
|
||||
DBUG_ASSERT(blt == &builtin_select);
|
||||
push_select(first_select);
|
||||
@@ -12900,7 +12901,7 @@ LEX::parse_optimizer_hints(const Lex_comment_st &hints_str)
|
||||
}
|
||||
|
||||
|
||||
void LEX::resolve_optimizer_hints()
|
||||
void LEX::resolve_optimizer_hints_in_last_select()
|
||||
{
|
||||
SELECT_LEX *select_lex;
|
||||
if (likely(select_stack_top))
|
||||
|
@@ -1390,6 +1390,7 @@ public:
|
||||
uint get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg);
|
||||
void print(THD *thd, String *str, enum_query_type query_type);
|
||||
void print_lock_type(String *str);
|
||||
void print_hints(THD *thd, String *hint_str);
|
||||
void print_item_list(THD *thd, String *str, enum_query_type query_type);
|
||||
void print_set_clause(THD *thd, String *str, enum_query_type query_type);
|
||||
void print_on_duplicate_key_clause(THD *thd, String *str,
|
||||
@@ -3747,7 +3748,7 @@ public:
|
||||
DBUG_RETURN(select_lex);
|
||||
}
|
||||
|
||||
void resolve_optimizer_hints();
|
||||
void resolve_optimizer_hints_in_last_select();
|
||||
|
||||
SELECT_LEX *current_select_or_default()
|
||||
{
|
||||
|
@@ -32105,35 +32105,10 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
return;
|
||||
}
|
||||
|
||||
char buff[NAME_LEN];
|
||||
String hint_str(buff, sizeof(buff), system_charset_info);
|
||||
hint_str.length(0);
|
||||
if (thd->lex->opt_hints_global)
|
||||
{
|
||||
char tmp_buff[NAME_LEN];
|
||||
String hints_tmp(tmp_buff, sizeof(tmp_buff), system_charset_info);
|
||||
hints_tmp.length(0);
|
||||
if (select_number == 1)
|
||||
{
|
||||
if (opt_hints_qb)
|
||||
opt_hints_qb->append_qb_hint(thd, &hints_tmp);
|
||||
thd->lex->opt_hints_global->print(thd, &hints_tmp);
|
||||
}
|
||||
else if (opt_hints_qb)
|
||||
opt_hints_qb->append_qb_hint(thd, &hints_tmp);
|
||||
|
||||
if (hints_tmp.length() > 0)
|
||||
{
|
||||
hint_str.append(STRING_WITH_LEN("/*+ "));
|
||||
hint_str.append(hints_tmp);
|
||||
hint_str.append(STRING_WITH_LEN("*/ "));
|
||||
}
|
||||
}
|
||||
|
||||
if (hint_str.length() > 0 && (sel_type == SELECT_CMD ||
|
||||
sel_type == INSERT_CMD ||
|
||||
sel_type == REPLACE_CMD))
|
||||
str->append(hint_str);
|
||||
if (sel_type == SELECT_CMD ||
|
||||
sel_type == INSERT_CMD ||
|
||||
sel_type == REPLACE_CMD)
|
||||
print_hints(thd, str);
|
||||
|
||||
/* First add options */
|
||||
if (options & SELECT_STRAIGHT_JOIN)
|
||||
@@ -32190,8 +32165,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
if (sel_type == UPDATE_CMD || sel_type == DELETE_CMD)
|
||||
{
|
||||
str->append(get_explainable_cmd_name(sel_type));
|
||||
if (hint_str.length() > 0)
|
||||
str->append(hint_str);
|
||||
print_hints(thd, str);
|
||||
}
|
||||
if (sel_type == DELETE_CMD)
|
||||
{
|
||||
@@ -32318,6 +32292,36 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
}
|
||||
|
||||
|
||||
void st_select_lex::print_hints(THD *thd,
|
||||
String *str)
|
||||
{
|
||||
if (!thd->lex->opt_hints_global)
|
||||
return;
|
||||
|
||||
constexpr LEX_CSTRING header={STRING_WITH_LEN("/*+ ")};
|
||||
str->append(header);
|
||||
uint32 len_before_hints= str->length();
|
||||
if (select_number == 1)
|
||||
{
|
||||
if (opt_hints_qb)
|
||||
opt_hints_qb->append_qb_hint(thd, str);
|
||||
thd->lex->opt_hints_global->print(thd, str);
|
||||
}
|
||||
else if (opt_hints_qb)
|
||||
opt_hints_qb->append_qb_hint(thd, str);
|
||||
|
||||
if (str->length() > len_before_hints)
|
||||
{
|
||||
// Some hints were printed, close the hint string
|
||||
str->append(STRING_WITH_LEN("*/ "));
|
||||
}
|
||||
else
|
||||
{
|
||||
// No hints were added, rollback the previouly added header
|
||||
str->length(len_before_hints - header.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Change the select_result object of the JOIN.
|
||||
|
||||
|
@@ -1015,10 +1015,6 @@ public:
|
||||
{
|
||||
return Binary_string::append(s);
|
||||
}
|
||||
bool append(const char *s)
|
||||
{
|
||||
return append(s, (uint) strlen(s));
|
||||
}
|
||||
inline bool append(char chr)
|
||||
{
|
||||
return Binary_string::append_char(chr);
|
||||
|
@@ -9005,6 +9005,7 @@ query_specification:
|
||||
opt_having_clause
|
||||
opt_window_clause
|
||||
{
|
||||
Lex->resolve_optimizer_hints_in_last_select();
|
||||
$$= Lex->pop_select();
|
||||
}
|
||||
;
|
||||
@@ -9018,6 +9019,7 @@ select_into_query_specification:
|
||||
opt_having_clause
|
||||
opt_window_clause
|
||||
{
|
||||
Lex->resolve_optimizer_hints_in_last_select();
|
||||
$$= Lex->pop_select();
|
||||
}
|
||||
;
|
||||
@@ -9157,7 +9159,6 @@ query_expression_body:
|
||||
query_simple
|
||||
{
|
||||
Lex->push_select($1);
|
||||
Lex->resolve_optimizer_hints();
|
||||
if (!($$= Lex->create_unit($1)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@@ -13604,7 +13605,7 @@ insert:
|
||||
insert_field_spec opt_insert_update opt_returning
|
||||
insert_stmt_end
|
||||
{
|
||||
Lex->resolve_optimizer_hints();
|
||||
Lex->resolve_optimizer_hints_in_last_select();
|
||||
Lex->mark_first_table_as_inserting();
|
||||
thd->get_stmt_da()->reset_current_row_for_warning(0);
|
||||
}
|
||||
@@ -13624,8 +13625,9 @@ replace:
|
||||
Select->set_lock_for_tables($5, true, false);
|
||||
}
|
||||
insert_field_spec opt_returning
|
||||
stmt_end
|
||||
insert_stmt_end
|
||||
{
|
||||
Lex->resolve_optimizer_hints_in_last_select();
|
||||
Lex->mark_first_table_as_inserting();
|
||||
thd->get_stmt_da()->reset_current_row_for_warning(0);
|
||||
}
|
||||
@@ -13641,7 +13643,7 @@ insert_start: {
|
||||
;
|
||||
|
||||
stmt_end: {
|
||||
Lex->resolve_optimizer_hints();
|
||||
Lex->resolve_optimizer_hints_in_last_select();
|
||||
Lex->pop_select(); //main select
|
||||
if (Lex->check_main_unit_semantics())
|
||||
MYSQL_YYABORT;
|
||||
@@ -14008,7 +14010,7 @@ delete:
|
||||
{
|
||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||
MYSQL_YYABORT;
|
||||
Lex->resolve_optimizer_hints();
|
||||
Lex->resolve_optimizer_hints_in_last_select();
|
||||
}
|
||||
;
|
||||
|
||||
|
Reference in New Issue
Block a user