I have a recursive CTE definition (graph
) in Postgres that involves cycle detection: fiddle
CREATE TABLE relationships (
subject_type,
subject_id,
subject_relation,
resource_type,
resource_id,
relationship
)AS VALUES(
'subject_type1',
'subject_id1',
'subject_relation1',
'resource_type1',
'resource_id1',
'relationship1');
CREATE TABLE type_restrictions (
subject_type,
subject_relation,
resource_type,
relationship
)AS VALUES(
'subject_type1',
'subject_relation1',
'resource_type1',
'relationship1');
CREATE VIEW graph AS WITH RECURSIVE
relationship_graph(subject_type, subject_id, subject_relation, resource_type, resource_id, relationship, depth, is_cycle, path)
AS(SELECT
r.subject_type, r.subject_id, r.subject_relation,
r.resource_type, r.resource_id,
r.relationship,
0,
false,
ARRAY[ROW(r.resource_type, r.resource_id, r.relationship, r.subject_type, r.subject_id, r.subject_relation)]
FROM relationships r
INNER JOIN type_restrictions tr
ON
r.subject_type = tr.subject_type AND
r.resource_type = tr.resource_type AND
r.relationship = tr.relationship
UNION
SELECT
g.subject_type,
g.subject_id,
g.subject_relation,
r.resource_type,
r.resource_id,
r.relationship,
g.depth + 1,
ROW(r.resource_type, r.resource_id, r.relationship, r.subject_type, r.subject_id, r.subject_relation) = ANY(path),
path || ROW(r.resource_type, r.resource_id, r.relationship, r.subject_type, r.subject_id, r.subject_relation)
FROM relationship_graph g, relationships r
WHERE
g.resource_type = r.subject_type AND
g.resource_id = r.subject_id AND
g.relationship = r.subject_relation AND
NOT is_cycle )
SELECT * FROM relationship_graph WHERE depth < 3;
When I try to create this view I get the following error from Postgres:
ERROR: column "path" has pseudo-type record[]
I am following the exact guide as specified in the official Postgres documentation. See https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-CYCLE (example 3).
I'm not seeing the obvious reason for this error, could someone assist?
I expect the ARRAY[ROW]
types to not be ARRAY[RECORD]
, and I don't expect an error. Unless the postgres documentation is wrong, it seems that this should work.
row
constructor by default yields arecord
type: doc. Since you're collecting all fields of therelationships
table row into the array element, you could just as wellarray[r]::r[]
. That would save you all the needless retyping of those fields and the resulting type would no longer be an anonymousrecord[]
but arelationships[]
array instead. Tables can be used as types this way.