diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-07-31 17:56:27 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-07-31 17:56:27 -0400 |
commit | 3786b9b4668743b99e837fe276e14be1f1bdfde9 (patch) | |
tree | 6674d832fc55b76d4391d2b647b9e11b48ce134c /src/backend/parser/parse_cte.c | |
parent | 63aba79c7f1f06422b22e2b44fdcb563bbc3f7a5 (diff) | |
download | postgresql-3786b9b4668743b99e837fe276e14be1f1bdfde9.tar.gz postgresql-3786b9b4668743b99e837fe276e14be1f1bdfde9.zip |
Fix WITH attached to a nested set operation (UNION/INTERSECT/EXCEPT).
Parse analysis neglected to cover the case of a WITH clause attached to an
intermediate-level set operation; it only handled WITH at the top level
or WITH attached to a leaf-level SELECT. Per report from Adam Mackler.
In HEAD, I rearranged the order of SelectStmt's fields to put withClause
with the other fields that can appear on non-leaf SelectStmts. In back
branches, leave it alone to avoid a possible ABI break for third-party
code.
Back-patch to 8.4 where WITH support was added.
Diffstat (limited to 'src/backend/parser/parse_cte.c')
-rw-r--r-- | src/backend/parser/parse_cte.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c index 2a7d4cd0724..d04fb6dec14 100644 --- a/src/backend/parser/parse_cte.c +++ b/src/backend/parser/parse_cte.c @@ -678,6 +678,18 @@ checkWellFormedRecursion(CteState *cstate) if (cstate->selfrefcount != 1) /* shouldn't happen */ elog(ERROR, "missing recursive reference"); + /* WITH mustn't contain self-reference, either */ + if (stmt->withClause) + { + cstate->curitem = i; + cstate->innerwiths = NIL; + cstate->selfrefcount = 0; + cstate->context = RECURSION_SUBLINK; + checkWellFormedRecursionWalker((Node *) stmt->withClause->ctes, + cstate); + Assert(cstate->innerwiths == NIL); + } + /* * Disallow ORDER BY and similar decoration atop the UNION. These * don't make sense because it's impossible to figure out what they @@ -933,7 +945,7 @@ checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate) cstate); checkWellFormedRecursionWalker((Node *) stmt->lockingClause, cstate); - break; + /* stmt->withClause is intentionally ignored here */ break; case SETOP_EXCEPT: if (stmt->all) @@ -952,6 +964,7 @@ checkWellFormedSelectStmt(SelectStmt *stmt, CteState *cstate) cstate); checkWellFormedRecursionWalker((Node *) stmt->lockingClause, cstate); + /* stmt->withClause is intentionally ignored here */ break; default: elog(ERROR, "unrecognized set op: %d", |