Re: [PATCH] Allow multiple recursive self-references

From: Denis Hirn <denis(dot)hirn(at)uni-tuebingen(dot)de>
To: Peter Eisentraut <peter(dot)eisentraut(at)enterprisedb(dot)com>, Zhihong Yu <zyu(at)yugabyte(dot)com>
Cc: vignesh C <vignesh21(at)gmail(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Pantelis Theodosiou <ypercube(at)gmail(dot)com>, David Fetter <david(at)fetter(dot)org>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: [PATCH] Allow multiple recursive self-references
Date: 2021-08-30 10:52:31
Message-ID: D1A25F17-B840-4385-8371-7579200B9C11@uni-tuebingen.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> This well-formedness check apparently needs to be enhanced to allow for more than two branches in the union.

The UNION operators' left associativity causes this problem. Currently, the recursive term
must be enclosed in parentheses to make this example work:

> WITH RECURSIVE nodes(x) AS (
> SELECT 59
> UNION
> (SELECT aa FROM edge JOIN nodes ON bb=x
> UNION
> SELECT bb FROM edge JOIN nodes ON aa=x)
> )
> SELECT x FROM nodes;

The current well-formedness check assumes the left argument of the top most UNION [ALL]
to be the non-recursive term. This allows for arbitrarily many non-recursive terms, and
exactly one recursive term. This should not be changed because later stages expect this
structure. But this left-deep UNION [ALL] tree does not suffice anymore. Therefore, the
ctequery field of the CommonTableExpr must be rewritten –– I think.

Let's take a look at another example:

> WITH RECURSIVE nodes(x) AS (
> SELECT 59
> UNION
> SELECT 42
> UNION
> SELECT aa FROM edge JOIN nodes ON bb=x
> UNION -- Top most UNION operator
> SELECT bb FROM edge JOIN nodes ON aa=x
> )
> SELECT x FROM nodes;

This would be parsed left-deep as:
((SELECT 59 UNION SELECT 42) UNION SELECT aa ...) UNION SELECT bb ...

The proposed rewriting should be able to detect that (SELECT 59 UNION SELECT 42) does
not contain any recursive references and therefore pull the term upwards in the tree,
leaving us with:

(SELECT 59 UNION SELECT 42) UNION (SELECT aa ... UNION SELECT bb ...)

Which would be the equivalent of:

> WITH RECURSIVE nodes(x) AS (
> (SELECT 59
> UNION
> SELECT 42)
> UNION -- Top most UNION operator
> (SELECT aa FROM edge JOIN nodes ON bb=x
> UNION
> SELECT bb FROM edge JOIN nodes ON aa=x)
> )
> SELECT x FROM nodes;

I am not sure if this patch should introduce such a rewriting.
Any thoughts on this?

Best,
–– Denis

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Ajin Cherian 2021-08-30 12:18:06 Re: Failure of subscription tests with topminnow
Previous Message David Rowley 2021-08-30 10:44:13 Re: Avoid choose invalid number of partitions (src/backend/executor/nodeAgg.c)