Skip to content

Commit 615ebcf

Browse files
author
Volodymyr Verovkin
committed
Bug#37560280 Incorrect behavior with EXPLAIN and subqueries
EXPLAIN could execute a stored function in a subquery when the subquery created a derived table, e.g.: EXPLAIN SELECT * FROM (SELECT f()) AS a; This issue was caused by Table_ref::materializable_is_const(), which incorrectly treated a function call as a constant expression. Now, we ensure that a derived table subquery containing a stored function call is not considered constant. Change-Id: Id73d567b3617da1523996e8ee0ed73b4879451ad (cherry picked from commit 2830b52f5515af4f7e9330492593446b215b004a)
1 parent 6488f27 commit 615ebcf

File tree

11 files changed

+99
-43
lines changed

11 files changed

+99
-43
lines changed

mysql-test/r/partition_locking.result

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5030,9 +5030,9 @@ Handler_read_next 12
50305030
UNLOCK TABLES;
50315031
EXPLAIN SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1');
50325032
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5033-
1 SIMPLE t2 p1 const PRIMARY PRIMARY 4 const # 100.00 NULL
5033+
1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where
50345034
Warnings:
5035-
Note 1003 /* select#1 */ select '1' AS `a`,'1' AS `b` from `test`.`t2` where true
5035+
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` = <cache>(`sf_a_from_t1b_d`('1')))
50365036
FLUSH STATUS;
50375037
START TRANSACTION;
50385038
SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1');
@@ -5086,9 +5086,9 @@ Handler_read_next 12
50865086
UNLOCK TABLES;
50875087
EXPLAIN SELECT * FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1');
50885088
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5089-
1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL
5089+
1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where
50905090
Warnings:
5091-
Note 1003 /* select#1 */ select '8' AS `a`,'8' AS `b` from `test`.`t2` where true
5091+
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` = <cache>((7 + `sf_a_from_t1b_d`('1'))))
50925092
FLUSH STATUS;
50935093
START TRANSACTION;
50945094
SELECT * FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1');
@@ -5138,9 +5138,9 @@ Handler_read_next 7
51385138
UNLOCK TABLES;
51395139
EXPLAIN SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
51405140
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5141-
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE
5141+
1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL
51425142
Warnings:
5143-
Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where false
5143+
Note 1003 /* select#1 */ select '2' AS `a`,'2' AS `b` from `test`.`t2` where ((2 = `sf_a_from_t1b_d`('1')))
51445144
FLUSH STATUS;
51455145
START TRANSACTION;
51465146
SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
@@ -5322,9 +5322,9 @@ Handler_read_next 12
53225322
UNLOCK TABLES;
53235323
EXPLAIN SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1');
53245324
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5325-
1 SIMPLE t2 p1 const PRIMARY PRIMARY 4 const # 100.00 NULL
5325+
1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where
53265326
Warnings:
5327-
Note 1003 /* select#1 */ select (`sf_add_1`('1') - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`('1') AS `sf_add_hello(b)` from `test`.`t2` where true
5327+
Note 1003 /* select#1 */ select (`sf_add_1`(`test`.`t2`.`a`) - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`(`test`.`t2`.`b`) AS `sf_add_hello(b)` from `test`.`t2` where (`test`.`t2`.`a` = <cache>(`sf_a_from_t1b_d`('1')))
53285328
FLUSH STATUS;
53295329
START TRANSACTION;
53305330
SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1');
@@ -5378,9 +5378,9 @@ Handler_read_next 12
53785378
UNLOCK TABLES;
53795379
EXPLAIN SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1');
53805380
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5381-
1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL
5381+
1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where
53825382
Warnings:
5383-
Note 1003 /* select#1 */ select (`sf_add_1`('8') - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`('8') AS `sf_add_hello(b)` from `test`.`t2` where true
5383+
Note 1003 /* select#1 */ select (`sf_add_1`(`test`.`t2`.`a`) - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`(`test`.`t2`.`b`) AS `sf_add_hello(b)` from `test`.`t2` where (`test`.`t2`.`a` = <cache>((7 + `sf_a_from_t1b_d`('1'))))
53845384
FLUSH STATUS;
53855385
START TRANSACTION;
53865386
SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1');
@@ -5430,9 +5430,9 @@ Handler_read_next 7
54305430
UNLOCK TABLES;
54315431
EXPLAIN SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
54325432
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5433-
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE
5433+
1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL
54345434
Warnings:
5435-
Note 1003 /* select#1 */ select (`sf_add_1`(`test`.`t2`.`a`) - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`(`test`.`t2`.`b`) AS `sf_add_hello(b)` from `test`.`t2` where false
5435+
Note 1003 /* select#1 */ select (`sf_add_1`('2') - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`('2') AS `sf_add_hello(b)` from `test`.`t2` where ((2 = `sf_a_from_t1b_d`('1')))
54365436
FLUSH STATUS;
54375437
START TRANSACTION;
54385438
SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
@@ -5652,7 +5652,7 @@ ROLLBACK;
56525652
UNLOCK TABLES;
56535653
EXPLAIN UPDATE t2 SET b = CONCAT('+', b) WHERE a = sf_a_from_t1b_d('1');
56545654
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5655-
1 UPDATE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where
5655+
1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where
56565656
Warnings:
56575657
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1'))
56585658
FLUSH STATUS;
@@ -5734,7 +5734,7 @@ ROLLBACK;
57345734
UNLOCK TABLES;
57355735
EXPLAIN UPDATE t2 SET b = CONCAT('+', b) WHERE a = 7 + sf_a_from_t1b_d('1');
57365736
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5737-
1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
5737+
1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where
57385738
Warnings:
57395739
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1')))
57405740
FLUSH STATUS;
@@ -5808,9 +5808,9 @@ ROLLBACK;
58085808
UNLOCK TABLES;
58095809
EXPLAIN UPDATE t2 SET b = CONCAT('+', b) WHERE a = sf_a_from_t1b_d('1') AND a = 2;
58105810
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
5811-
1 UPDATE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE
5811+
1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
58125812
Warnings:
5813-
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where ()
5813+
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1')))
58145814
FLUSH STATUS;
58155815
START TRANSACTION;
58165816
UPDATE t2 SET b = CONCAT('+', b) WHERE a = sf_a_from_t1b_d('1') AND a = 2;
@@ -6064,7 +6064,7 @@ ROLLBACK;
60646064
UNLOCK TABLES;
60656065
EXPLAIN UPDATE t2 SET b = sf_add_hello(b) WHERE a = sf_a_from_t1b_d('1');
60666066
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6067-
1 UPDATE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where
6067+
1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where
60686068
Warnings:
60696069
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1'))
60706070
FLUSH STATUS;
@@ -6146,7 +6146,7 @@ ROLLBACK;
61466146
UNLOCK TABLES;
61476147
EXPLAIN UPDATE t2 SET b = sf_add_hello(b) WHERE a = 7 + sf_a_from_t1b_d('1');
61486148
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6149-
1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
6149+
1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where
61506150
Warnings:
61516151
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1')))
61526152
FLUSH STATUS;
@@ -6220,9 +6220,9 @@ ROLLBACK;
62206220
UNLOCK TABLES;
62216221
EXPLAIN UPDATE t2 SET b = sf_add_hello(b) WHERE a = sf_a_from_t1b_d('1') AND a = 2;
62226222
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6223-
1 UPDATE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE
6223+
1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
62246224
Warnings:
6225-
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where ()
6225+
Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1')))
62266226
FLUSH STATUS;
62276227
START TRANSACTION;
62286228
UPDATE t2 SET b = sf_add_hello(b) WHERE a = sf_a_from_t1b_d('1') AND a = 2;
@@ -6482,7 +6482,7 @@ ROLLBACK;
64826482
UNLOCK TABLES;
64836483
EXPLAIN UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = sf_a_from_t1b_d('1');
64846484
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6485-
1 UPDATE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where
6485+
1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where; Using temporary
64866486
Warnings:
64876487
Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1'))
64886488
FLUSH STATUS;
@@ -6568,7 +6568,7 @@ ROLLBACK;
65686568
UNLOCK TABLES;
65696569
EXPLAIN UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = 7 + sf_a_from_t1b_d('1');
65706570
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6571-
1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
6571+
1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where; Using temporary
65726572
Warnings:
65736573
Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1')))
65746574
FLUSH STATUS;
@@ -6644,9 +6644,9 @@ ROLLBACK;
66446644
UNLOCK TABLES;
66456645
EXPLAIN UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
66466646
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6647-
1 UPDATE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE
6647+
1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
66486648
Warnings:
6649-
Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where ()
6649+
Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1')))
66506650
FLUSH STATUS;
66516651
START TRANSACTION;
66526652
UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
@@ -6899,7 +6899,7 @@ ROLLBACK;
68996899
UNLOCK TABLES;
69006900
EXPLAIN DELETE FROM t2 WHERE a = sf_a_from_t1b_d('1');
69016901
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6902-
1 DELETE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where
6902+
1 DELETE t2 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 Using where
69036903
Warnings:
69046904
Note 1003 delete from `test`.`t2` where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1'))
69056905
FLUSH STATUS;
@@ -6977,7 +6977,7 @@ ROLLBACK;
69776977
UNLOCK TABLES;
69786978
EXPLAIN DELETE FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1');
69796979
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6980-
1 DELETE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
6980+
1 DELETE t2 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 Using where
69816981
Warnings:
69826982
Note 1003 delete from `test`.`t2` where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1')))
69836983
FLUSH STATUS;
@@ -7049,9 +7049,9 @@ ROLLBACK;
70497049
UNLOCK TABLES;
70507050
EXPLAIN DELETE FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2;
70517051
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
7052-
1 DELETE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE
7052+
1 DELETE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where
70537053
Warnings:
7054-
Note 1003 delete from `test`.`t2` where ()
7054+
Note 1003 delete from `test`.`t2` where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1')))
70557055
FLUSH STATUS;
70567056
START TRANSACTION;
70577057
DELETE FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2;

mysql-test/r/sp.result

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6377,24 +6377,24 @@ Warnings:
63776377
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = 1)
63786378
EXPLAIN SELECT * FROM t1 WHERE c1=f1();
63796379
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6380-
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index
6380+
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using where; Using index
63816381
Warnings:
6382-
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = `f1`())
6382+
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = <cache>(`f1`()))
63836383
EXPLAIN SELECT * FROM v1 WHERE c1=1;
63846384
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
63856385
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index
63866386
Warnings:
63876387
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = 1)
63886388
EXPLAIN SELECT * FROM v1 WHERE c1=f1();
63896389
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6390-
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index
6390+
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using where; Using index
63916391
Warnings:
6392-
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = `f1`())
6392+
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = <cache>(`f1`()))
63936393
EXPLAIN SELECT * FROM t1 WHERE c1=f2(10);
63946394
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
6395-
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index
6395+
1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using where; Using index
63966396
Warnings:
6397-
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = `f2`(10))
6397+
Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = <cache>(`f2`(10)))
63986398
EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1);
63996399
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
64006400
1 SIMPLE t1 NULL index NULL c1 5 NULL 5 20.00 Using where; Using index

mysql-test/t/partition_locking.test

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,6 +2938,11 @@ DROP TABLE t1, t2;
29382938
--echo #
29392939
--echo # Test subqueries/stored functions with UPDATE/DELETE/SELECT
29402940
--echo #
2941+
# Bug#37560280:
2942+
# The EXPLAIN plan for queries with the sf_a_from_t1b_d() function call
2943+
# differs from the actual execution plan because constant folding
2944+
# is performed in the actual plan but not in EXPLAIN.
2945+
29412946
CREATE TABLE tq (id int PRIMARY KEY auto_increment, query varchar(255), not_select tinyint);
29422947
CREATE TABLE tsq (id int PRIMARY KEY auto_increment, subquery varchar(255), can_be_locked tinyint);
29432948
CREATE TABLE t1 (a int, b varchar(255), PRIMARY KEY (a), KEY (b))

sql/item_func.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8319,6 +8319,8 @@ bool Item_func_sp::val_json(Json_wrapper *result) {
83198319
bool Item_func_sp::execute() {
83208320
THD *thd = current_thd;
83218321

8322+
assert(!thd->lex->is_explain() || thd->lex->is_explain_analyze);
8323+
83228324
Internal_error_handler_holder<View_error_handler, Table_ref> view_handler(
83238325
thd, context->view_error_handler, context->view_error_handler_arg);
83248326

sql/sql_derived.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@ bool Table_ref::optimize_derived(THD *thd) {
16701670
// at execution time (in fact, it will get confused and crash if it has
16711671
// already been materialized).
16721672
if (!thd->lex->using_hypergraph_optimizer()) {
1673-
if (materializable_is_const() &&
1673+
if (materializable_is_const(thd) &&
16741674
(create_materialized_table(thd) || materialize_derived(thd)))
16751675
return true;
16761676
}

sql/sql_lex.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,8 @@ class Query_expression {
729729
bool prepared; ///< All query blocks in query expression are prepared
730730
bool optimized; ///< All query blocks in query expression are optimized
731731
bool executed; ///< Query expression has been executed
732+
///< Explain mode: query expression refers stored function
733+
bool m_has_stored_program{false};
732734

733735
/// Object to which the result for this query expression is sent.
734736
/// Not used if we materialize directly into a parent query expression's
@@ -773,6 +775,8 @@ class Query_expression {
773775
/// multi-level ORDER, i.e. we have a "simple table".
774776
bool is_simple() const { return m_query_term->term_type() == QT_QUERY_BLOCK; }
775777

778+
bool has_stored_program() const { return m_has_stored_program; }
779+
776780
/// Values for Query_expression::cleaned
777781
enum enum_clean_state {
778782
UC_DIRTY, ///< Unit isn't cleaned
@@ -4999,4 +5003,12 @@ Table_ref *nest_join(THD *thd, Query_block *select, Table_ref *embedding,
49995003
mem_root_deque<Table_ref *> *jlist, size_t table_cnt,
50005004
const char *legend);
50015005
void get_select_options_str(ulonglong options, std::string *str);
5006+
5007+
template <typename T>
5008+
inline bool WalkQueryExpression(Query_expression *query_expr, enum_walk walk,
5009+
T &&functor) {
5010+
return query_expr->walk(&Item::walk_helper_thunk<T>, walk,
5011+
reinterpret_cast<uchar *>(&functor));
5012+
}
5013+
50025014
#endif /* SQL_LEX_INCLUDED */

sql/sql_optimizer.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5696,12 +5696,16 @@ bool JOIN::extract_const_tables() {
56965696
1. are dependent upon other tables, or
56975697
2. have no exact statistics, or
56985698
3. are full-text searched
5699+
4. a derived table which has a stored function
56995700
*/
5701+
const bool explain_mode = thd->lex->is_explain();
57005702
if ((table->s->system || table->file->stats.records <= 1 ||
57015703
all_partitions_pruned_away) &&
57025704
!tab->dependent && // 1
57035705
(table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) && // 2
5704-
!tl->is_fulltext_searched()) // 3
5706+
!tl->is_fulltext_searched() && // 3
5707+
!(explain_mode && tl->is_view_or_derived() &&
5708+
tl->has_stored_program())) // 4
57055709
mark_const_table(tab, nullptr);
57065710
break;
57075711
}
@@ -5855,6 +5859,7 @@ bool JOIN::extract_func_dependent_tables() {
58555859
6. are not going to be used, typically because they are streamed
58565860
instead of materialized
58575861
(see Query_expression::can_materialize_directly_into_result()).
5862+
7. key evaluated in stored program in EXPLAIN mode
58585863
*/
58595864
if (eq_part.is_prefix(table->key_info[key].user_defined_key_parts) &&
58605865
!tl->is_fulltext_searched() && // 1
@@ -5863,7 +5868,9 @@ bool JOIN::extract_func_dependent_tables() {
58635868
!(tab->join_cond() &&
58645869
tab->join_cond()->cost().IsExpensive()) && // 4
58655870
!(table->file->ha_table_flags() & HA_BLOCK_CONST_TABLE) && // 5
5866-
table->is_created()) { // 6
5871+
table->is_created() && // 6
5872+
!(thd->lex->is_explain() &&
5873+
start_keyuse->val->has_stored_program())) { // 7
58675874
if (table->key_info[key].flags & HA_NOSAME) {
58685875
if (const_ref == eq_part) { // Found everything for ref.
58695876
ref_changed = true;
@@ -6296,7 +6303,7 @@ static ha_rows get_quick_record_count(THD *thd, JOIN_TAB *tab, ha_rows limit,
62966303
return 0;
62976304
}
62986305
DBUG_PRINT("warning", ("Couldn't use record count on const keypart"));
6299-
} else if (tl->is_table_function() || tl->materializable_is_const()) {
6306+
} else if (tl->is_table_function() || tl->materializable_is_const(thd)) {
63006307
tl->fetch_number_of_rows();
63016308
return tl->table->file->stats.records;
63026309
}
@@ -11510,6 +11517,13 @@ bool evaluate_during_optimization(const Item *item, const Query_block *select) {
1151011517
// If the Item does not access any tables, it can always be evaluated.
1151111518
if (item->const_item()) return true;
1151211519

11520+
// Do not evaluate stored procedure in EXPLAIN
11521+
if (current_thd->lex->is_explain() &&
11522+
WalkItem(item, enum_walk::PREFIX, [](const Item *curitem) {
11523+
return curitem->has_stored_program();
11524+
}))
11525+
return false;
11526+
1151311527
return !item->has_subquery() || (select->active_options() &
1151411528
OPTION_NO_SUBQUERY_DURING_OPTIMIZATION) == 0;
1151511529
}

sql/sql_select.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,8 +2385,9 @@ bool init_ref_part(THD *thd, unsigned part_no, Item *val, bool *cond_guard,
23852385
key_part_info, key_buff, nullable);
23862386
if (unlikely(!s_key || thd->is_error())) return true;
23872387

2388-
if (used_tables & ~INNER_TABLE_BIT) {
2389-
/* Comparing against a non-constant. */
2388+
if (used_tables & ~INNER_TABLE_BIT ||
2389+
(thd->lex->is_explain() &&
2390+
val->has_stored_program())) { /* Comparing against a non-constant. */
23902391
ref->key_copy[part_no] = s_key;
23912392
} else {
23922393
/*

0 commit comments

Comments
 (0)