In Postgres 9.1 or later you can use data-modifying CTEs to make this fast, safe, simple and elegant:
WITH x AS (
INSERT INTO restaurant(name, x, y)
SELECT 'restaurantname', valuex, valuey
WHERE NOT EXISTS (SELECT 1 FROM restaurant WHERE name = 'restaurantname')
RETURNING rest_id -- returns auto-generated id (from sequence)
)
, y AS (
INSERT INTO restaurant_location(rest_id, ...)
SELECT rest_id, ...
FROM x -- only produces rows after a successful INSERT
)
--- more chained INSERTs here?
INSERT INTO restaurant_foodtype(rest_id, ...)
SELECT rest_id, ...
FROM x;
The first INSERT is only executed if 'restaurantname' is not found. There is a super-tiny race-condition if multiple queries should try the same in the same instance. If you have a UNIQUE constraint on restaurant.name (like you should judging from your description), the worst that could happen is that among concurring queries only the first would succeed while the others return with a unique violation (doing nothing). Chances are, however, you will never see this, because it is very unlikely to happen.
The RETURNING clause returns the automatically generated rest_id - I assume rest_idis a serial column.
The following INSERT queries only generate rows if the first one succeeded.
Finish the series with be a plain INSERT.
With PostgreSQL 8.1 I would write a plpgsql function to achieve the same.
But, really, you'd better upgrade to a current version.