aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_target.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2021-02-01 13:54:59 +0100
committerPeter Eisentraut <peter@eisentraut.org>2021-02-01 14:32:51 +0100
commit3696a600e2292d43c00949ddf0352e4ebb487e5b (patch)
tree11f19c8c9e5757c44b8da02d0e1f7b41f8ec5f13 /src/backend/parser/parse_target.c
parentbb513b364b4fe31574574c8d0afbb2255268b321 (diff)
downloadpostgresql-3696a600e2292d43c00949ddf0352e4ebb487e5b.tar.gz
postgresql-3696a600e2292d43c00949ddf0352e4ebb487e5b.zip
SEARCH and CYCLE clauses
This adds the SQL standard feature that adds the SEARCH and CYCLE clauses to recursive queries to be able to do produce breadth- or depth-first search orders and detect cycles. These clauses can be rewritten into queries using existing syntax, and that is what this patch does in the rewriter. Reviewed-by: Vik Fearing <vik@postgresfriends.org> Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/db80ceee-6f97-9b4a-8ee8-3ba0c58e5be2@2ndquadrant.com
Diffstat (limited to 'src/backend/parser/parse_target.c')
-rw-r--r--src/backend/parser/parse_target.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 7eaa076771a..51ecc16c42e 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -399,8 +399,23 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle,
{
CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
TargetEntry *ste;
+ List *tl = GetCTETargetList(cte);
+ int extra_cols = 0;
+
+ /*
+ * RTE for CTE will already have the search and cycle columns
+ * added, but the subquery won't, so skip looking those up.
+ */
+ if (cte->search_clause)
+ extra_cols += 1;
+ if (cte->cycle_clause)
+ extra_cols += 2;
+ if (extra_cols &&
+ attnum > list_length(tl) &&
+ attnum <= list_length(tl) + extra_cols)
+ break;
- ste = get_tle_by_resno(GetCTETargetList(cte), attnum);
+ ste = get_tle_by_resno(tl, attnum);
if (ste == NULL || ste->resjunk)
elog(ERROR, "CTE %s does not have attribute %d",
rte->eref->aliasname, attnum);