]> granicus.if.org Git - postgresql/commitdiff
Fix markTargetListOrigin() to not fail on a simple-Var reference to a
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Oct 2008 22:20:17 +0000 (22:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Oct 2008 22:20:17 +0000 (22:20 +0000)
recursive CTE that we're still in progress of analyzing.  Add a similar guard
to the similar code in expandRecordVariable(), and tweak regression tests to
cover this case.  Per report from Dickson S. Guedes.

src/backend/parser/parse_target.c
src/test/regress/expected/with.out
src/test/regress/sql/with.sql

index 3ead26194e37758b429b42f1581081f959893f26..ed54abe70398e037c1255583b5ad7531cb1a2458 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.165 2008/10/04 21:56:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.166 2008/10/05 22:20:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -297,8 +297,16 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
                        /* not a simple relation, leave it unmarked */
                        break;
                case RTE_CTE:
-                       /* CTE reference: copy up from the subquery */
-                       if (attnum != InvalidAttrNumber)
+                       /*
+                        * CTE reference: copy up from the subquery, if possible.
+                        * If the RTE is a recursive self-reference then we can't do
+                        * anything because we haven't finished analyzing it yet.
+                        * However, it's no big loss because we must be down inside
+                        * the recursive term of a recursive CTE, and so any markings
+                        * on the current targetlist are not going to affect the results
+                        * anyway.
+                        */
+                       if (attnum != InvalidAttrNumber && !rte->self_reference)
                        {
                                CommonTableExpr *cte = GetCTEForRTE(pstate, rte);
                                TargetEntry *ste;
@@ -1195,8 +1203,9 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
                         */
                        break;
                case RTE_CTE:
+                       /* CTE reference: examine subquery's output expr */
+                       if (!rte->self_reference)
                        {
-                               /* CTE reference: examine subquery's output expr */
                                CommonTableExpr *cte = GetCTEForRTE(pstate, rte);
                                TargetEntry *ste;
 
index ac91642c7bdc5b74a07e51a812341138d774c3ce..65afc1a0c670b5d2fbe63bff38a76220ad942792 100644 (file)
@@ -96,20 +96,20 @@ INSERT INTO department VALUES (7, 5, 'G');
 WITH RECURSIVE subdepartment AS
 (
        -- non recursive term
-       SELECT * FROM department WHERE name = 'A'
+       SELECT name as root_name, * FROM department WHERE name = 'A'
        UNION ALL
        -- recursive term
-       SELECT d.* FROM department AS d, subdepartment AS sd
+       SELECT sd.root_name, d.* FROM department AS d, subdepartment AS sd
                WHERE d.parent_department = sd.id
 )
 SELECT * FROM subdepartment ORDER BY name;
- id | parent_department | name 
-----+-------------------+------
-  1 |                 0 | A
-  2 |                 1 | B
-  3 |                 2 | C
-  4 |                 2 | D
-  6 |                 4 | F
root_name | id | parent_department | name 
+-----------+----+-------------------+------
A         |  1 |                 0 | A
A         |  2 |                 1 | B
A         |  3 |                 2 | C
A         |  4 |                 2 | D
A         |  6 |                 4 | F
 (5 rows)
 
 -- extract all departments under 'A' with "level" number
index 0ad59abdc9fe495a3ed93a01c483eedcfc63fd1b..cd8831f4b15654df48a914db44acea817f61bcb0 100644 (file)
@@ -68,12 +68,12 @@ INSERT INTO department VALUES (7, 5, 'G');
 WITH RECURSIVE subdepartment AS
 (
        -- non recursive term
-       SELECT * FROM department WHERE name = 'A'
+       SELECT name as root_name, * FROM department WHERE name = 'A'
 
        UNION ALL
 
        -- recursive term
-       SELECT d.* FROM department AS d, subdepartment AS sd
+       SELECT sd.root_name, d.* FROM department AS d, subdepartment AS sd
                WHERE d.parent_department = sd.id
 )
 SELECT * FROM subdepartment ORDER BY name;