Things that come to mind, in addition to having the user SELECT-only and revoking privileges on functions:
Read-only transaction. When a transaction is started by
BEGIN READ ONLY
, orSET TRANSACTION READ ONLY
as its first instruction, it cannot write anything, independantly of the user permissions.At the client side, if you want to restrict it to one
SELECT
, better use a SQL submission function that does not accept several queries bundled into one. For instance, the swiss-knifePQexec
method of thelibpq
API does accept such queries and so does every driver function that is built on top of it, like PHP'spg_query
.http://sqlfiddle.com/ is a service dedicated to running arbitrary SQL statements which may be seen somehow as a proof-of-concept that it's doable without being hacked or DDos'ed all day long.