Re: Dynamically filtering a CTE?

From: "W(dot) Trevor King" <wking(at)tremily(dot)us>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: Dynamically filtering a CTE?
Date: 2018-04-20 16:22:32
Message-ID: 20180420162232.GM27577@valgrind.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Thu, Apr 19, 2018 at 05:28:00PM -0700, David G. Johnston wrote:
> On Thursday, April 19, 2018, W. Trevor King wrote:
> > Is there an idiomatic way to approach this problem?
>
> I would use pl/pgsql as the language and build a query using a
> combination of text literals and the format() function - invoking
> via pl/pgsql's EXECUTE command.

That works. I've ended up with:

CREATE OR REPLACE FUNCTION ancestors(condition text)
RETURNS TABLE(id integer, ancestors integer[]) AS
$$
BEGIN
RETURN QUERY EXECUTE format('
WITH RECURSIVE _ancestors(id, ancestors) AS (
SELECT
item.id AS id,
ARRAY[item.ancestor_id] AS ancestors
FROM items AS item
%s
UNION ALL
SELECT
descendant.id AS id,
descendant.ancestors || ancestor.ancestor_id AS ancestors
FROM _ancestors AS descendant
JOIN items as ancestor
ON descendant.ancestors[array_length(descendant.ancestors, 1)] = ancestor.id
)
SELECT
id,
ancestors[1:array_length(ancestors, 1) - 1] AS ancestors -- drop the trailing NULL
FROM _ancestors
WHERE ancestors[array_length(ancestors, 1)] IS NULL -- remove non-terminal recursion
', condition);
END
$$ LANGUAGE plpgsql STABLE;

which you can use like:

SELECT * FROM ancestors('WHERE item.id = 62324721');

or (without filtering, for the full, slow CTE):

SELECT * FROM ancestors('');

Thanks,
Trevor

--
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message David G. Johnston 2018-04-20 16:33:22 Re: Dynamically filtering a CTE?
Previous Message Tatsuo Ishii 2018-04-20 16:14:30 Re: Postgresql database encryption