CREATE OR REPLACE FUNCTION raise_exception(in_message TEXT)
RETURNS BOOLEAN
LANGUAGE plpgsql
AS $$
BEGIN
    RAISE EXCEPTION '%', in_message;
    RETURN true;
END;
$$;

CREATE OR REPLACE FUNCTION lock_conflict(TEXT, TEXT)
RETURNS BOOLEAN
STRICT
LANGUAGE SQL
AS $$
SELECT
  CASE
  WHEN $1 NOT IN (
    'AccessShareLock', 'RowShareLock', 'RowExclusiveLock',
    'ShareUpdateExclusiveLock', 'ShareLock', 'ShareRowExclusiveLock',
    'ExclusiveLock', 'AccessExclusiveLock'
    )
  OR $2 NOT IN (
    'AccessShareLock', 'RowShareLock', 'RowExclusiveLock',
    'ShareUpdateExclusiveLock', 'ShareLock', 'ShareRowExclusiveLock',
    'ExclusiveLock', 'AccessExclusiveLock'
    ) THEN
    raise_exception('Both arguments must be valid lock names.')
  WHEN $1 = 'AccessShareLock' THEN
    CASE WHEN $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'RowShareLock' THEN
    CASE WHEN $2 = 'ExclusiveLock' OR
       $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'RowExclusiveLock' THEN
    CASE WHEN $2 = 'ShareLock' OR
       $2 = 'ShareRowExclusiveLock' OR
       $2 = 'ExclusiveLock' OR
       $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'ShareUpdateExclusiveLock' THEN
    CASE WHEN $2 = 'ShareUpdateExclusiveLock' OR
       $2 = 'ShareLock' OR
       $2 = 'ShareRowExclusiveLock' OR
       $2 = 'ExclusiveLock' OR
       $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'ShareLock' THEN
    CASE WHEN $2 = 'RowExclusiveLock' OR
       $2 = 'ShareUpdateExclusiveLock' OR
       $2 = 'ShareRowExclusiveLock' OR
       $2 = 'ExclusiveLock' OR
       $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'ShareRowExclusiveLock' THEN
    CASE WHEN $2 = 'RowExclusiveLock' OR
       $2 = 'ShareUpdateExclusiveLock' OR
       $2 = 'ShareLock' OR
       $2 = 'ShareRowExclusiveLock' OR
       $2 = 'ExclusiveLock' OR
       $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'ExclusiveLock' THEN
    CASE WHEN $2 = 'RowShareLock' OR 
       $2 = 'RowExclusiveLock' OR
       $2 = 'ShareUpdateExclusiveLock' OR
       $2 = 'ShareLock' OR
       $2 = 'ShareRowExclusiveLock' OR
       $2 = 'ExclusiveLock' OR
       $2 = 'AccessExclusiveLock' THEN
         TRUE
    ELSE
         FALSE
    END
  WHEN $1 = 'AccessExclusiveLock' THEN
    TRUE
  END
$$;
