Q: RETURNING data from updatable view not working? I have two simple tables person and address with inserts going through an updatable view person_details.
Relations and trigger
CREATE TABLE address (
  id          serial PRIMARY KEY,
  street      varchar,
  town        varchar NOT NULL
);

CREATE TABLE person (
  id          serial PRIMARY KEY,
  first_name  varchar,
  family_name varchar NOT NULL,
  address     integer REFERENCES address
);

The owner obviously has full permissions, but regular users can only access the data through a view which includes details from both tables:
CREATE VIEW person_details AS
  SELECT p.id, p.first_name, p.family_name, a.street, a.town
  FROM person p
  LEFT JOIN address a ON a.id = p.address;

The view is updatable such that regular users can INSERT into the tables underlying the view:
GRANT SELECT, INSERT ON person_details TO public;

I have defined the trigger to propagate the INSERT to the tables and all works just fine:
CREATE FUNCTION t0ii_person_details() RETURNS trigger AS $$
DECLARE
  addr  integer;
BEGIN
  -- Want at least a town to insert anything into table address.
  IF (NEW.town IS NOT NULL) THEN
    INSERT INTO address(street, town)
      VALUES (NEW.street, NEW.town)
      RETURNING id INTO addr;
  ELSE
    addr := NULL;
  END IF;

  INSERT INTO person(first_name, family_name, address)
    VALUES (NEW.first_name, NEW.family_name, addr);
  RETURN NEW;
END; $$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER t0ii_person_details
  INSTEAD OF INSERT ON person_details
  FOR EACH ROW EXECUTE PROCEDURE t0ii_person_details();

INSERT - ok
A simple insert:
pfams=# INSERT INTO person_details (first_name, family_name, town) VALUES ('John', 'Doe', 'Eders');
INSERT 0 1

pfams=# SELECT * FROM person_details;
 id | first_name | family_name | street |  town
----+------------+-------------+--------+--------
  1 | John       | Doe         |        | Eders
(1 row)

INSERT RETURNING id - not ok
However, if I want to return the newly assigned id (originating from the person table where it is generated from a sequence, serial data type) directly from the INSERT statement, then I get nothing back:
pfams=# INSERT INTO person_details (first_name, family_name, town) VALUES ('Jim', 'Doe', 'Eders') RETURNING id;
 id
----

(1 row)

INSERT 0 1

But the data is there:
pfams=# SELECT * FROM person_details;
 id | first_name | family_name | street |  town
----+------------+-------------+--------+--------
  1 | John       | Doe         |        | Eders
  2 | Jim        | Doe         |        | Eders
(2 rows)

What am I missing here?
pfams=# SELECT version();
                                               version
-----------------------------------------------------------------------------------------------------
 PostgreSQL 9.3.6 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 32-bit


A: You were so close ;) you only need to update NEW.id in your trigger.
CREATE FUNCTION t0ii_person_details() RETURNS trigger AS $$
DECLARE
  addr  integer;
BEGIN
  -- Want at least a town to insert anything into table address.
  IF (NEW.town IS NOT NULL) THEN
    INSERT INTO address(street, town)
      VALUES (NEW.street, NEW.town)
      RETURNING id INTO addr;
  ELSE
    addr := NULL;
  END IF;

  INSERT INTO person(first_name, family_name, address)
    VALUES (NEW.first_name, NEW.family_name, addr) 
    -- here is the only change I made
    RETURNING id INTO NEW.id;
  RETURN NEW;
END; $$ LANGUAGE plpgsql SECURITY DEFINER;

