Skip to content

Commit

Permalink
Fixed mdev-15162 Query with CTE hangs if assignment operator (:=) is …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
igorbabaev committed Feb 6, 2018
1 parent 465979e commit f271100
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
13 changes: 13 additions & 0 deletions mysql-test/r/cte_recursive.result
Original file line number Diff line number Diff line change
Expand Up @@ -3079,3 +3079,16 @@ ERROR 21000: The used SELECT statements have a different number of columns
DROP TABLE a_tbl;
WITH RECURSIVE x AS (SELECT 1,2 UNION ALL SELECT 1 FROM x) SELECT * FROM x;
ERROR 21000: The used SELECT statements have a different number of columns
#
# 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
12 changes: 12 additions & 0 deletions mysql-test/t/cte_recursive.test
Original file line number Diff line number Diff line change
Expand Up @@ -2113,3 +2113,15 @@ DROP TABLE a_tbl;

--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
WITH RECURSIVE x AS (SELECT 1,2 UNION ALL SELECT 1 FROM x) SELECT * FROM x;

--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;
6 changes: 5 additions & 1 deletion sql/item_func.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "set_var.h"
#include "debug_sync.h"
#include "sql_base.h"
#include "sql_cte.h"

#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {}
Expand Down Expand Up @@ -4514,10 +4515,13 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
TABLE_LIST *derived;
for (derived= unit->derived;
derived;
derived= derived->select_lex->master_unit()->derived)
derived= unit->derived)
{
derived->set_materialized_derived();
derived->prohibit_cond_pushdown= true;
if (unit->with_element && unit->with_element->is_recursive)
break;
unit= derived->select_lex->master_unit();
}
}

Expand Down

0 comments on commit f271100

Please sign in to comment.