Re: Rule ON DELETE, to perform to DELETE querys !

Поиск
Список
Период
Сортировка
От Luis Sousa
Тема Re: Rule ON DELETE, to perform to DELETE querys !
Дата
Msg-id 3B2F77A0.F108D805@ualg.pt
обсуждение исходный текст
Ответ на Rule ON DELETE, to perform to DELETE querys !  (Luis Sousa <llsousa@ualg.pt>)
Список pgsql-admin
Hello Tom

We didn't correct yet the bug that restarts the postmaster, but we already find out
a way of deleting in two tables.
Using inside in the rule for delete a function that deletes in two tables we can get
the results that we want.

There's the code that i used to do that:

----- RULE:

CREATE RULE "deleteturnodocente" AS ON DELETE TO "docentesturno"
 DO INSTEAD (
 SELECT

delete_pessoalevento_pessoal(OLD.cod_disciplina,OLD.var,OLD.tipo,OLD.turno,OLD.periodo,OLD.periodo_pessoal,OLD.idpessoal)
AS ok;
 );

----- FUNCTIONS:

CREATE FUNCTION
delete_pessoalevento_pessoal(text,text,text,integer,integer,integer,integer)
RETURNS boolean AS '
 DECLARE
  f_disciplina ALIAS FOR $1;
  f_var ALIAS FOR $2;
  f_tipo ALIAS FOR $3;
  f_turno ALIAS FOR $4;
  f_id_periodo ALIAS FOR $5;
  f_id_periodo_pe ALIAS FOR $6;
  f_id_pessoal ALIAS FOR $7;

 BEGIN
  DELETE FROM "pessoalEvento"
   WHERE disciplina = f_disciplina
     AND var = f_var
     AND tipo = f_tipo
     AND turno = f_turno
     AND "idPeriodo" = f_id_periodo
     AND "idPeriodoPe" = f_id_periodo_pe
     AND "idPessoal" = f_id_pessoal;

         DELETE FROM evento
   WHERE disciplina = f_disciplina
     AND var = f_var
     AND tipo = f_tipo
     AND turno = f_turno
     AND "idPeriodo" = f_id_periodo
     AND "idPeriodoE" = f_id_periodo_pe;

  RETURN 1;
 END;'
LANGUAGE 'plpgsql';

Tom Lane wrote:

> Luis Sousa <llsousa@ualg.pt> writes:
> >     CREATE RULE "deletetables" AS ON DELETE TO "tables"
> >          DO INSTEAD (
> >          DELETE FROM table2
> >                 WHERE id = OLD.id;
> >          DELETE FROM table1
> >                 WHERE id=OLD.id
> >            );
>
> It turns out you are running into the same problem as Pete Leonard:
> both the same 7.1 bug, and the same difficulty that your rule won't
> work even without the bug.  See attached.
>
>                         regards, tom lane
>
> ------- Forwarded Message
>
> Date:    Tue, 12 Jun 2001 14:05:36 -0400
> From:    Tom Lane <tgl@sss.pgh.pa.us>
> To:      Pete Leonard <pete@hero.com>
> cc:      pgsql-general@postgresql.org
> Subject: Re: [GENERAL] stumped on view/rule/delete problem.
>
> Pete Leonard <pete@hero.com> writes:
> > create table foo (
> > id    serial,
> > name  varchar(50)
> > );
>
> > create table bar (
> > foo_id        integer,
> > name2 varchar(50)
> > );
>
> > create view foobar as
> > select f.id, f.name, b.name2 from foo f, bar b where (f.id = b.foo_id);
>
> > create rule delete_foobar as on delete to foobar
> > do instead (
> > delete from foo where id=OLD.id;
> > delete from bar where foo_id = OLD.id;
> > );
>
> > running the command
> > delete from foobar where id=1;
> > causes the DB to hang.  only way out is an immediate restart of the DB.
>
> This is a bug, for which I propose the attached patch against 7.1.2
> (it'll apply to 7.1 also, but you might as well update to 7.1.2 before
> recompiling...).
>
> However, the above rule will not produce the result you want anyway,
> because OLD is essentially a macro for the view.  As soon as you delete
> a row from foo, there's no longer any such row in the view, so the
> delete from bar doesn't find anything to delete.  Example:
>
> regression=# insert into foo values(1,'a');
> INSERT 157940 1
> regression=# insert into foo values(2,'b');
> INSERT 157941 1
> regression=# insert into bar values(1,'aa');
> INSERT 157942 1
> regression=# insert into bar values(2,'bb');
> INSERT 157943 1
> regression=# select * from foobar;
>  id | name | name2
> ----+------+-------
>   1 | a    | aa
>   2 | b    | bb
> (2 rows)
>
> regression=# delete from foobar where id=1;
> DELETE 0
> regression=# select * from foobar;
>  id | name | name2
> ----+------+-------
>   2 | b    | bb
> (1 row)
>
> regression=# select * from foo;
>  id | name
> ----+------
>   2 | b
> (1 row)
>
> regression=# select * from bar;
>  foo_id | name2
> --------+-------
>       1 | aa
>       2 | bb
> (2 rows)
>
> What you probably want instead is to make bar reference foo as a foreign
> key with ON DELETE CASCADE; then the rule for foobar only needs to
> delete from foo explicitly, and the additional delete from bar is done
> implicitly by the foreign key trigger.
>
>                         regards, tom lane
>
> *** src/backend/rewrite/rewriteHandler.c.orig   Thu May  3 13:47:49 2001
> --- src/backend/rewrite/rewriteHandler.c        Tue Jun 12 13:32:49 2001
> ***************
> *** 82,88 ****
>
>         /*
>          * Adjust rule action and qual to offset its varnos, so that we can
> !        * merge its rtable into the main parsetree's rtable.
>          *
>          * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries
>          * will be in the SELECT part, and we have to modify that rather than
> --- 82,88 ----
>
>         /*
>          * Adjust rule action and qual to offset its varnos, so that we can
> !        * merge its rtable with the main parsetree's rtable.
>          *
>          * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries
>          * will be in the SELECT part, and we have to modify that rather than
> ***************
> *** 99,121 ****
>                                    PRS2_OLD_VARNO + rt_length, rt_index, 0);
>
>         /*
> !        * We want the main parsetree's rtable to end up as the concatenation
> !        * of its original contents plus those of all the relevant rule
> !        * actions.  Also store same into all the rule_action rtables. Some of
> !        * the entries may be unused after we finish rewriting, but if we
> !        * tried to clean those out we'd have a much harder job to adjust RT
> !        * indexes in the query's Vars.  It's OK to have unused RT entries,
> !        * since planner will ignore them.
>          *
> !        * NOTE KLUGY HACK: we assume the parsetree rtable had at least one entry
> !        * to begin with (OK enough, else where'd the rule come from?).
> !        * Because of this, if multiple rules nconc() their rtable additions
> !        * onto parsetree->rtable, they'll all see the same rtable because
> !        * they all have the same list head pointer.
> !        */
> !       parsetree->rtable = nconc(parsetree->rtable,
> !                                                         sub_action->rtable);
> !       sub_action->rtable = parsetree->rtable;
>
>         /*
>          * Each rule action's jointree should be the main parsetree's jointree
> --- 99,117 ----
>                                    PRS2_OLD_VARNO + rt_length, rt_index, 0);
>
>         /*
> !        * Generate expanded rtable consisting of main parsetree's rtable
> !        * plus rule action's rtable; this becomes the complete rtable for the
> !        * rule action.  Some of the entries may be unused after we finish
> !        * rewriting, but if we tried to clean those out we'd have a much harder
> !        * job to adjust RT indexes in the query's Vars.  It's OK to have unused
> !        * RT entries, since planner will ignore them.
>          *
> !        * NOTE: because planner will destructively alter rtable, we must ensure
> !        * that rule action's rtable is separate and shares no substructure with
> !        * the main rtable.  Hence do a deep copy here.
> !        */
> !       sub_action->rtable = nconc((List *) copyObject(parsetree->rtable),
> !                                                          sub_action->rtable);
>
>         /*
>          * Each rule action's jointree should be the main parsetree's jointree
> ***************
> *** 128,133 ****
> --- 124,132 ----
>          * data for the quals.  We don't want the original rtindex to be
>          * joined twice, however, so avoid keeping it if the rule action
>          * mentions it.
> +        *
> +        * As above, the action's jointree must not share substructure with
> +        * the main parsetree's.
>          */
>         if (sub_action->jointree != NULL)
>         {
> ***************
> *** 193,205 ****
>    * occurrence of the given rt_index as a top-level join item (we do not look
>    * for it within join items; this is OK because we are only expecting to find
>    * it as an UPDATE or DELETE target relation, which will be at the top level
> !  * of the join).  Returns modified jointree list --- original list is not
> !  * changed.
>    */
>   static List *
>   adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
>   {
> !       List       *newjointree = listCopy(parsetree->jointree->fromlist);
>         List       *jjt;
>
>         if (removert)
> --- 192,204 ----
>    * occurrence of the given rt_index as a top-level join item (we do not look
>    * for it within join items; this is OK because we are only expecting to find
>    * it as an UPDATE or DELETE target relation, which will be at the top level
> !  * of the join).  Returns modified jointree list --- this is a separate copy
> !  * sharing no nodes with the original.
>    */
>   static List *
>   adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
>   {
> !       List       *newjointree = copyObject(parsetree->jointree->fromlist);
>         List       *jjt;
>
>         if (removert)
>
> ------- End of Forwarded Message
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster


В списке pgsql-admin по дате отправления:

Предыдущее
От: Juan Manuel Sende
Дата:
Сообщение: Re: PGDATESTYLE
Следующее
От: "Rainer Mager"
Дата:
Сообщение: RE: High memory usage