Re: changing an update via rules - caught in recursion - Mailing list pgsql-general

From Lauren Matheson
Subject Re: changing an update via rules - caught in recursion
Date
Msg-id 1058490298.11154.15.camel@bic
Whole thread Raw
In response to Re: changing an update via rules - caught in recursion  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-general
Resolution for the archives:

I created a view essentially like:
CREATE VIEW editor_contact AS SELECT c.contact_id, c.password, (SELECT
csg.securitygroup_id FROM contactsecuritygroup csg WHERE
((csg.contact_id = c.contact_id) AND (csg.primarygroup = true)) ORDER BY
csg.securitygroup_id LIMIT 1) AS primarygroupname FROM contact c;

then a function to keep the unique primary group:
CREATE FUNCTION contactsecgrp_setprimarygrpname(varchar(255),varchar(255))
RETURNS bool
DECLARE
  new_contact_id ALIAS FOR $1;
  new_primarygroupname ALIAS FOR $2;
BEGIN
  DELETE from contactsecuritygroup WHERE contact_id=NEW_contact_id and securitygroup_id!=NEW_primarygroupname and
primarygroup=true;
  IF (SELECT count(contact_id) from contactsecuritygroup where securitygroup_id=NEW_primarygroupname and
contact_id=NEW_contact_id)=0
    THEN INSERT into contactsecuritygroup (contact_id, securitygroup_id, primarygroup) VALUES (NEW_contact_id,
NEW_primarygroupname,true); 
    ELSE UPDATE contactsecuritygroup set primarygroup=true WHERE contact_id=NEW_contact_id and
securitygroup_id=NEW_primarygroupname;
  END IF;
  RETURN true;
END;

then three rules to update the contact table and call the function to
update the grouping table:

CREATE RULE editor_contact_delete
AS ON DELETE TO editor_contact
DO INSTEAD
DELETE FROM contact WHERE (contact.contact_id = old.contact_id);

CREATE RULE editor_contact_insert
AS ON INSERT TO editor_contact
DO INSTEAD (
INSERT INTO contact (contact_id, password) VALUES (new.contact_id, new.password);
SELECT contactsecgrp_setprimarygrpname(new.contact_id, new.primarygroupname) AS contactsecgrp_setprimarygrpname;
);

CREATE RULE editor_contact_update
AS ON UPDATE TO editor_contact
DO INSTEAD (
UPDATE contact SET contact_id = new.contact_id, password = new.password WHERE (contact.contact_id = old.contact_id);
SELECT contactsecgrp_setprimarygrpname(new.contact_id, new.primarygroupname) AS contactsecgrp_setprimarygrpname;
);

A cascade on update/delete rule on the constraint between the contact
and group tables handles changes to contact_id, and removes group links
with their contact.

Peace,
Lauren.

On Wed, 2003-07-16 at 17:45, Tom Lane wrote:
> Lauren Matheson <lmatheson@ivcf.ca> writes:
> > CREATE RULE contactsecgrp_update_1pg_them
> > AS ON UPDATE TO contactsecuritygroup
> > WHERE NEW.primarygroup=true
> > DO
> > UPDATE contactsecuritygroup SET primarygroup=false WHERE contact_id =
> > NEW.contact_id and securitygroup_id != NEW.securitygroup_id;
>
> You can't do that, because a rule is a macro expanded during query
> preparation, and the above is going to lead to infinite recursion
> during macro expansion.  (No, the WHERE clause does not stop it,
> because the actual value of WHERE is only checked at run time.)
>
> You could make this sort of adjustment in a BEFORE UPDATE trigger,
> though.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: the planner will ignore your desire to choose an index scan if your
>       joining column's datatypes do not match



pgsql-general by date:

Previous
From: Joe Conway
Date:
Subject: Re: Strange behaviour of Postgresql (Postgresql 7.3.3
Next
From: Bruce Momjian
Date:
Subject: Re: [PATCHES] bytea char escaping