Skip to content

Commit 0585540

Browse files
committed
MDEV-16629 "Table Does Not Exist" Error from Recursive CTE Query Inside Function
When processing a query containing with clauses a call of the function check_dependencies_in_with_clauses() before opening tables used in the query is necessary if with clauses include specifications of recursive CTEs. This call was missing if such a query belonged to a stored function. This caused misbehavior of the server: it could report a fake error as in the test case for MDEV-16629 or the executed query could hang as in the test cases for MDEV-16661 and MDEV-15151.
1 parent 400cf01 commit 0585540

File tree

3 files changed

+133
-1
lines changed

3 files changed

+133
-1
lines changed

mysql-test/r/cte_recursive.result

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3263,3 +3263,61 @@ select 3, 0*(@d:=@d+1) from qn where @d<1
32633263
select * from qn;
32643264
ERROR 42000: This version of MariaDB doesn't yet support 'mix of ALL and DISTINCT UNION operations in recursive CTE spec'
32653265
drop table t1;
3266+
#
3267+
# MDEV-16629: function with recursive CTE using a base table
3268+
#
3269+
CREATE TABLE t1 (id int);
3270+
INSERT INTO t1 VALUES (0), (1),(2);
3271+
WITH recursive cte AS
3272+
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
3273+
SELECT count(id) FROM cte;
3274+
count(id)
3275+
4
3276+
CREATE OR REPLACE FUNCTION func() RETURNS int
3277+
RETURN
3278+
(
3279+
WITH recursive cte AS
3280+
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
3281+
SELECT count(id) FROM cte
3282+
);
3283+
SELECT func();
3284+
func()
3285+
4
3286+
DROP FUNCTION func;
3287+
DROP TABLE t1;
3288+
#
3289+
# MDEV-16661: function with recursive CTE using no base tables
3290+
# (fixed by the patch for MDEV-16629)
3291+
#
3292+
CREATE OR REPLACE FUNCTION func() RETURNS int
3293+
RETURN
3294+
(
3295+
WITH RECURSIVE cte AS
3296+
(SELECT 1 as id UNION SELECT * FROM cte)
3297+
SELECT count(id) FROM cte
3298+
);
3299+
SELECT func();
3300+
func()
3301+
1
3302+
DROP FUNCTION func;
3303+
#
3304+
# MDEV-15151: function with recursive CTE using no base tables
3305+
# (duplicate of MDEV-16661)
3306+
#
3307+
connection default;
3308+
CREATE TABLE t1 (id int KEY);
3309+
INSERT INTO t1 VALUES (0), (1),(2);
3310+
CREATE OR REPLACE FUNCTION func() RETURNS int
3311+
RETURN
3312+
(
3313+
WITH recursive cte AS
3314+
(SELECT 1 a UNION SELECT cte.* FROM cte natural join t1)
3315+
SELECT * FROM cte limit 1
3316+
);
3317+
SELECT func();;
3318+
connect con1,localhost,root,,;
3319+
KILL QUERY 4;
3320+
DROP FUNCTION func;
3321+
DROP TABLE t1;
3322+
disconnect con1;
3323+
connection default;

mysql-test/t/cte_recursive.test

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,3 +2282,75 @@ select 3, 0*(@d:=@d+1) from qn where @d<1
22822282
select * from qn;
22832283

22842284
drop table t1;
2285+
2286+
--echo #
2287+
--echo # MDEV-16629: function with recursive CTE using a base table
2288+
--echo #
2289+
2290+
CREATE TABLE t1 (id int);
2291+
INSERT INTO t1 VALUES (0), (1),(2);
2292+
2293+
WITH recursive cte AS
2294+
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
2295+
SELECT count(id) FROM cte;
2296+
2297+
CREATE OR REPLACE FUNCTION func() RETURNS int
2298+
RETURN
2299+
(
2300+
WITH recursive cte AS
2301+
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
2302+
SELECT count(id) FROM cte
2303+
);
2304+
2305+
SELECT func();
2306+
2307+
DROP FUNCTION func;
2308+
DROP TABLE t1;
2309+
2310+
--echo #
2311+
--echo # MDEV-16661: function with recursive CTE using no base tables
2312+
--echo # (fixed by the patch for MDEV-16629)
2313+
--echo #
2314+
2315+
CREATE OR REPLACE FUNCTION func() RETURNS int
2316+
RETURN
2317+
(
2318+
WITH RECURSIVE cte AS
2319+
(SELECT 1 as id UNION SELECT * FROM cte)
2320+
SELECT count(id) FROM cte
2321+
);
2322+
2323+
SELECT func();
2324+
2325+
DROP FUNCTION func;
2326+
2327+
--echo #
2328+
--echo # MDEV-15151: function with recursive CTE using no base tables
2329+
--echo # (duplicate of MDEV-16661)
2330+
--echo #
2331+
2332+
--connection default
2333+
2334+
CREATE TABLE t1 (id int KEY);
2335+
INSERT INTO t1 VALUES (0), (1),(2);
2336+
2337+
CREATE OR REPLACE FUNCTION func() RETURNS int
2338+
RETURN
2339+
(
2340+
WITH recursive cte AS
2341+
(SELECT 1 a UNION SELECT cte.* FROM cte natural join t1)
2342+
SELECT * FROM cte limit 1
2343+
);
2344+
2345+
--let $conid= `SELECT CONNECTION_ID()`
2346+
--send SELECT func();
2347+
2348+
--connect (con1,localhost,root,,)
2349+
--eval KILL QUERY $conid
2350+
--source include/restart_mysqld.inc
2351+
2352+
DROP FUNCTION func;
2353+
DROP TABLE t1;
2354+
--disconnect con1
2355+
2356+
--connection default

sql/sp_head.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "sql_array.h" // Dynamic_array
3030
#include "log_event.h" // Query_log_event
3131
#include "sql_derived.h" // mysql_handle_derived
32+
#include "sql_cte.h"
3233

3334
#ifdef USE_PRAGMA_IMPLEMENTATION
3435
#pragma implementation
@@ -3000,7 +3001,8 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
30003001
#endif
30013002

30023003
if (open_tables)
3003-
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
3004+
res= check_dependencies_in_with_clauses(m_lex->with_clauses_list) ||
3005+
instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
30043006

30053007
if (!res)
30063008
{

0 commit comments

Comments
 (0)