Commit 2ef41622 authored by Igor Babaev's avatar Igor Babaev

Fixed mdev-15162 Query with CTE hangs if assignment operator (:=) is used

If setting user variable was used in the specification of a recursive CTE
then Item_func_set_user_var::fix_fields() went into an infinite loop.
parent bdb87c49
...@@ -3050,3 +3050,16 @@ Warnings: ...@@ -3050,3 +3050,16 @@ Warnings:
Note 1003 with recursive destinations as (select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !<in_optimizer>(`test`.`b`.`arrival`,<exists>(select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations` Note 1003 with recursive destinations as (select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !<in_optimizer>(`test`.`b`.`arrival`,<exists>(select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations`
set standard_compliant_cte=default; set standard_compliant_cte=default;
drop table flights; drop table flights;
#
# MDEV-15162: Setting user variable in recursive CTE
#
SET @c=1;
WITH RECURSIVE cte AS
(SELECT 5
UNION
SELECT @c:=@c+1 FROM cte WHERE @c<3)
SELECT * FROM cte;
5
5
2
3
...@@ -2085,3 +2085,15 @@ eval explain extended $q; ...@@ -2085,3 +2085,15 @@ eval explain extended $q;
set standard_compliant_cte=default; set standard_compliant_cte=default;
drop table flights; drop table flights;
--echo #
--echo # MDEV-15162: Setting user variable in recursive CTE
--echo #
SET @c=1;
WITH RECURSIVE cte AS
(SELECT 5
UNION
SELECT @c:=@c+1 FROM cte WHERE @c<3)
SELECT * FROM cte;
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "sp.h" #include "sp.h"
#include "set_var.h" #include "set_var.h"
#include "debug_sync.h" #include "debug_sync.h"
#include "sql_cte.h"
#ifdef NO_EMBEDDED_ACCESS_CHECKS #ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {} #define sp_restore_security_context(A,B) while (0) {}
...@@ -4703,10 +4704,13 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) ...@@ -4703,10 +4704,13 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
TABLE_LIST *derived; TABLE_LIST *derived;
for (derived= unit->derived; for (derived= unit->derived;
derived; derived;
derived= derived->select_lex->master_unit()->derived) derived= unit->derived)
{ {
derived->set_materialized_derived(); derived->set_materialized_derived();
derived->prohibit_cond_pushdown= true; derived->prohibit_cond_pushdown= true;
if (unit->with_element && unit->with_element->is_recursive)
break;
unit= derived->select_lex->master_unit();
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment