Re: PostgreSQL: Question about rules - Mailing list pgsql-general

From Jeremy Smith
Subject Re: PostgreSQL: Question about rules
Date
Msg-id 7353a39e0611171149m4a57b92by139284cb1fa94a0d@mail.gmail.com
Whole thread Raw
In response to Re: PostgreSQL: Question about rules  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: PostgreSQL: Question about rules  (Jeff Davis <pgsql@j-davis.com>)
List pgsql-general
On 11/16/06, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> Actually, the best way to do that is to attach a default to the view
> itself.
>
>         CREATE VIEW v AS SELECT ... ;
>         CREATE RULE ... for insert on v ... ;
>         ALTER TABLE v ALTER COLUMN c DEFAULT whatever;
>
> In this formulation the rule is not responsible for substituting any
> default values, it just does what it's told.  This is better than the
> COALESCE approach because the latter does the wrong thing if one is
> explicitly inserting NULL.

Hey - this is great information.  I'm now very close to having a
general and robust solution to my problem.  One problem remains with
using this approach: sequences.

alter table my_view alter column set default nextval('my_table_id_seq');

create rule my_view_ins as on insert to my_view do instead(
       insert into my_table(id, foo) values(new.id, new.foo);
       insert into my_child_table(id, foo) values(new.id, new.bar);
);

-- Works
insert into my_view(id, foo, bar) values (42, 'a foo', 'a bar');

-- Error - key (id)=(3) is not present in table "my_table"
insert into my_view(foo, bar) values('another foo', 'another bar');


Now, the default value for new.id gets evaluated *each time* I
reference new.id - meaning the rule's first insert sees N for new.id
while the rule's second insert sees N+1.  That is kind of odd - I
would think that the default value would get evaluated and then
assigned to new.id (since it is a concrete row), but that appears not
to be the case.

My stopgap solution to this is to call a PSQL/PL function for the body
of the rule, which can store new.id in a variable so it is evaluated
only once.  If there is a way to do this inside the rule without
resorting to creating a view, 3 rules and 3 functions for every child
table, I would love to hear about it!

Thanks for all the tips, Jeff and Tom.

Jeremy (Reposted this to the list; I accidentally replied only to Tom
the first time).

pgsql-general by date:

Previous
From: "Thomas H."
Date:
Subject: Re: Cannot rename file pg_xlog\0000.....
Next
From: "A. Kretschmer"
Date:
Subject: Re: Select slow over network