ars: I don't know if we have reached max depth or if it is just a waiting period. The major issues are:
1) Testability. you can write test cases against a stored proc. You cannot write test cases against a SQL query embedded in the middle of a function in another programming language.
2) Single point of control. You can have one function that runs the stored proc there and check properly for SQL injection, ensuring that everything is free of SQL injection as far as front-to-backend is concerned (and in Pg, that only leaves SQL injection issues in dynamic SQL which can be searched for and audited separately).
So that's why not to put it there.
As to changing the query.... I only use databases which come with transactional DDL so that's not an issue as long as inputs and outputs don't change. If the inputs and outputs have to change, we can handle that too with transactional DDL and the fact that we make the interfaces discoverable. In this case, we'd
BEGIN;
DROP FUNCTION IF EXISTS foo_bar(...);
CREATE OR REPLACE FUNCTION foo_bar(...)...;
COMMENT ON FUNCTION foo_bar(...) IS $$...$$;
COMMIT;
Because of the way Pg works this shouldn't really cause issues for currently running queries.
As for finding the right function, since these are all called on a declarative interface so you know what the function name is quickly, and so it is a matter of quickly finding it in a directory of SQL files.
As for testability, don't underrate this. You can insert data, run your tests, and roll back. So for example for our 1099-MISC and INT handling, we run more than 40 tests on a pre-written data set that we can run without ever committing to production and which will never conflict with production data (and therefore does not lock other users out). That's approx. 20 tests per sproc there.