Original query:

 WITH RECURSIVE c(requested, current) AS (
         VALUES ('AccessShareLock'::text,'AccessExclusiveLock'::text), ('RowShareLock'::text,'ExclusiveLock'::text), ('RowShareLock'::text,'AccessExclusiveLock'::text), ('RowExclusiveLock'::text,'ShareLock'::text), ('RowExclusiveLock'::text,'ShareRowExclusiveLock'::text), ('RowExclusiveLock'::text,'ExclusiveLock'::text), ('RowExclusiveLock'::text,'AccessExclusiveLock'::text), ('ShareUpdateExclusiveLock'::text,'ShareUpdateExclusiveLock'::text), ('ShareUpdateExclusiveLock'::text,'ShareLock'::text), ('ShareUpdateExclusiveLock'::text,'ShareRowExclusiveLock'::text), ('ShareUpdateExclusiveLock'::text,'ExclusiveLock'::text), ('ShareUpdateExclusiveLock'::text,'AccessExclusiveLock'::text), ('ShareLock'::text,'RowExclusiveLock'::text), ('ShareLock'::text,'ShareUpdateExclusiveLock'::text), ('ShareLock'::text,'ShareRowExclusiveLock'::text), ('ShareLock'::text,'ExclusiveLock'::text), ('ShareLock'::text,'AccessExclusiveLock'::text), ('ShareRowExclusiveLock'::text,'RowExclusiveLock'::text), ('ShareRowExclusiveLock'::text,'ShareUpdateExclusiveLock'::text), ('ShareRowExclusiveLock'::text,'ShareLock'::text), ('ShareRowExclusiveLock'::text,'ShareRowExclusiveLock'::text), ('ShareRowExclusiveLock'::text,'ExclusiveLock'::text), ('ShareRowExclusiveLock'::text,'AccessExclusiveLock'::text), ('ExclusiveLock'::text,'RowShareLock'::text), ('ExclusiveLock'::text,'RowExclusiveLock'::text), ('ExclusiveLock'::text,'ShareUpdateExclusiveLock'::text), ('ExclusiveLock'::text,'ShareLock'::text), ('ExclusiveLock'::text,'ShareRowExclusiveLock'::text), ('ExclusiveLock'::text,'ExclusiveLock'::text), ('ExclusiveLock'::text,'AccessExclusiveLock'::text), ('AccessExclusiveLock'::text,'AccessShareLock'::text), ('AccessExclusiveLock'::text,'RowShareLock'::text), ('AccessExclusiveLock'::text,'RowExclusiveLock'::text), ('AccessExclusiveLock'::text,'ShareUpdateExclusiveLock'::text), ('AccessExclusiveLock'::text,'ShareLock'::text), ('AccessExclusiveLock'::text,'ShareRowExclusiveLock'::text), ('AccessExclusiveLock'::text,'ExclusiveLock'::text), ('AccessExclusiveLock'::text,'AccessExclusiveLock'::text)
        ), l AS (
         SELECT ROW(pg_locks.locktype, pg_locks.database, pg_locks.relation::regclass::text, pg_locks.page, pg_locks.tuple, pg_locks.virtualxid, pg_locks.transactionid, pg_locks.classid, pg_locks.objid, pg_locks.objsubid) AS target,
            pg_locks.virtualtransaction,
            pg_locks.pid,
            pg_locks.mode,
            pg_locks.granted
           FROM pg_locks
        ), t AS (
         SELECT blocker.target AS blocker_target,
            blocker.pid AS blocker_pid,
            blocker.mode AS blocker_mode,
            blocked.target,
            blocked.pid,
            blocked.mode
           FROM l blocker
             JOIN l blocked ON NOT blocked.granted AND blocker.granted AND blocked.pid <> blocker.pid AND NOT blocked.target IS DISTINCT FROM blocker.target
             JOIN c ON c.requested = blocked.mode AND c.current = blocker.mode
        ), r AS (
         SELECT t.blocker_target::text AS blocker_target,
            t.blocker_pid,
            t.blocker_mode,
            1 AS depth,
            t.target::text AS target,
            t.pid,
            t.mode,
            (t.blocker_pid::text || ','::text) || t.pid::text AS seq
           FROM t
        UNION ALL
         SELECT blocker.blocker_target,
            blocker.blocker_pid,
            blocker.blocker_mode,
            blocker.depth + 1,
            blocked.target::text AS target,
            blocked.pid,
            blocked.mode,
            (blocker.seq || ','::text) || blocked.pid::text
           FROM r blocker
             JOIN t blocked ON blocked.blocker_pid = blocker.pid
          WHERE blocker.depth < 1000
        )
 SELECT r.blocker_target,
    r.blocker_pid,
    r.blocker_mode,
    r.depth,
    r.target,
    r.pid,
    r.mode,
    r.seq
   FROM r
  ORDER BY r.seq;