Original query:

 WITH RECURSIVE lock_composite(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)
        ), lock AS (
         SELECT pg_locks.pid,
            pg_locks.virtualtransaction,
            pg_locks.granted,
            pg_locks.mode,
            ROW(pg_locks.locktype,
                CASE pg_locks.locktype
                    WHEN 'relation'::text THEN concat_ws(';'::text, 'db:'::text || pg_database.datname::text, 'rel:'::text || pg_locks.relation::regclass::text)
                    WHEN 'extend'::text THEN concat_ws(';'::text, 'db:'::text || pg_database.datname::text, 'rel:'::text || pg_locks.relation::regclass::text)
                    WHEN 'page'::text THEN concat_ws(';'::text, 'db:'::text || pg_database.datname::text, 'rel:'::text || pg_locks.relation::regclass::text, 'page#'::text || pg_locks.page::text)
                    WHEN 'tuple'::text THEN concat_ws(';'::text, 'db:'::text || pg_database.datname::text, 'rel:'::text || pg_locks.relation::regclass::text, 'page#'::text || pg_locks.page::text, 'tuple#'::text || pg_locks.tuple::text)
                    WHEN 'transactionid'::text THEN pg_locks.transactionid::text
                    WHEN 'virtualxid'::text THEN pg_locks.virtualxid
                    WHEN 'object'::text THEN concat_ws(';'::text, 'class:'::text || pg_locks.classid::regclass::text, 'objid:'::text || pg_locks.objid, 'col#'::text || pg_locks.objsubid)
                    ELSE concat('db:'::text || pg_database.datname::text)
                END) AS target
           FROM pg_locks
             LEFT JOIN pg_database ON pg_database.oid = pg_locks.database
        ), waiting_lock AS (
         SELECT blocker.pid AS blocker_pid,
            blocked.pid,
            concat(blocked.mode, blocked.target) AS lock_target
           FROM lock blocker
             JOIN lock blocked ON NOT blocked.granted AND blocker.granted AND blocked.pid <> blocker.pid AND NOT blocked.target IS DISTINCT FROM blocker.target
             JOIN lock_composite c ON c.requested = blocked.mode AND c.current = blocker.mode
        ), acquired_lock AS (
         WITH waiting AS (
                 SELECT waiting_lock.lock_target,
                    count(waiting_lock.lock_target) AS wait_count
                   FROM waiting_lock
                  GROUP BY waiting_lock.lock_target
                )
         SELECT lock.pid,
            array_agg(concat(lock.mode, lock.target, ' + '::text || waiting.wait_count) ORDER BY waiting.wait_count DESC NULLS LAST) AS locks_acquired
           FROM lock
             LEFT JOIN waiting ON waiting.lock_target = concat(lock.mode, lock.target)
          WHERE lock.granted
          GROUP BY lock.pid
        ), blocking_lock AS (
         SELECT ARRAY[date_part('epoch'::text, act.query_start)::integer, blocker.pid] AS seq,
            0 AS depth,
            - 1 AS blocker_pid,
            blocker.pid,
            concat('Connect: ', act.usename, ' ', act.datname, ' ', COALESCE((host(act.client_addr) || ':'::text) || act.client_port, 'local'::text), '
SQL: ', replace(substr(COALESCE(act.query, 'N/A'::text), 1, 60), '
'::text, ' '::text), '
Acquired:
  ', array_to_string(blocker.locks_acquired[1:5] ||
                CASE
                    WHEN array_upper(blocker.locks_acquired, 1) > 5 THEN ('... '::text || ((array_upper(blocker.locks_acquired, 1) - 5)::text)) || ' more ...'::text
                    ELSE NULL::text
                END, '
  '::text)) AS lock_info,
            concat(to_char(act.query_start,
                CASE
                    WHEN age(act.query_start) > '24:00:00'::interval THEN 'Day DD Mon'::text
                    ELSE 'HH24:MI:SS'::text
                END), ' started
',
                CASE
                    WHEN act.wait_event IS NOT NULL THEN 'waiting'::text
                    ELSE act.state
                END, '
', date_trunc('second'::text, age(now(), act.query_start)), ' ago') AS lock_state
           FROM acquired_lock blocker
             LEFT JOIN monitoring.pg_stat_activity act USING (pid)
          WHERE (EXISTS ( SELECT 'x'
                   FROM waiting_lock blocked
                  WHERE blocked.blocker_pid = blocker.pid)) AND NOT (EXISTS ( SELECT 'x'
                   FROM waiting_lock blocked
                  WHERE blocked.pid = blocker.pid))
        UNION ALL
         SELECT blocker.seq || blocked.pid,
            blocker.depth + 1,
            blocker.pid,
            blocked.pid,
            concat('Connect: ', act.usename, ' ', act.datname, ' ', COALESCE((host(act.client_addr) || ':'::text) || act.client_port, 'local'::text), '
SQL: ', replace(substr(COALESCE(act.query, 'N/A'::text), 1, 60), '
'::text, ' '::text), '
Waiting: ', blocked.lock_target,
                CASE
                    WHEN acq.locks_acquired IS NOT NULL THEN '
Acquired:
  '::text || array_to_string(acq.locks_acquired[1:5] ||
                    CASE
                        WHEN array_upper(acq.locks_acquired, 1) > 5 THEN ('... '::text || ((array_upper(acq.locks_acquired, 1) - 5)::text)) || ' more ...'::text
                        ELSE NULL::text
                    END, '
  '::text)
                    ELSE NULL::text
                END) AS lock_info,
            concat(to_char(act.query_start,
                CASE
                    WHEN age(act.query_start) > '24:00:00'::interval THEN 'Day DD Mon'::text
                    ELSE 'HH24:MI:SS'::text
                END), ' started
',
                CASE
                    WHEN act.wait_event IS NOT NULL THEN 'waiting'::text
                    ELSE act.state
                END, '
', date_trunc('second'::text, age(now(), act.query_start)), ' ago') AS lock_state
           FROM blocking_lock blocker
             JOIN waiting_lock blocked ON blocked.blocker_pid = blocker.pid
             LEFT JOIN monitoring.pg_stat_activity act ON act.pid = blocked.pid
             LEFT JOIN acquired_lock acq ON acq.pid = blocked.pid
          WHERE blocker.depth < 5
        )
 SELECT concat(lpad('=> '::text, 4 * blocking_lock.depth, ' '::text), blocking_lock.pid::text) AS "PID",
    blocking_lock.lock_info AS "Lock Info",
    blocking_lock.lock_state AS "State"
   FROM blocking_lock
  ORDER BY blocking_lock.seq;