I can't speak specifically to Postgres, but, in my experience, there is nearly always a way to do what you want with bound parameters. No advanced features are required. It often results in poor performance and redundant code that is hard on the eyes. You will get what you deserve, but sometimes you don't have a choice.
Here is an example of the horror:
WHERE (:1 IS NULL OR :1 = item_id)
AND item_num BETWEEN NVL(:2,0) AND NVL(:2,9999999999)
AND item_date BETWEEN NVL(:3,'01-jan-1900') AND NVL(:3,'31-dec-4712')
AND item_name LIKE NVL(:4,'%')
CASE :5 WHEN 'NUM' THEN item_num WHEN 'DATE' THEN item_date ELSE item_name END,
CASE :6 WHEN 'NUM' THEN item_num WHEN 'DATE' THEN item_date ELSE item_name END
I am not advocating any of this but am pointing out that bind parameters can be abused in surprising ways if you are backed into a corner.