Обсуждение: can a trigger on insert -> update other tables?

Поиск
Список
Период
Сортировка

can a trigger on insert -> update other tables?

От
will trillich
Дата:
i've got a "_rating" table that, when a new record is added,
i'd like to have propagate through some other tables to update
running totals:

CREATE FUNCTION _rating_propagate( _rating ) RETURNS OPAQUE AS '
    DECLARE

        n ALIAS FOR $1;
        opinion   char(1) := upper(substring(n.rating from 1 for 1));

    BEGIN

        UPDATE sometable  SET fld = fld + 1 WHERE id = .... ;
        UPDATE othertable SET fld = fld + 1 WHERE id = .... ;
    [yada yada]
    END;
' LANGUAGE 'plpgsql';

CREATE TRIGGER _rating_propagate
    BEFORE INSERT ON _rating
    FOR EACH ROW EXECUTE PROCEDURE _rating_propagate( NEW );

INSERT INTO _rating VALUES ( ... );

the insert into _rating works fine, but none of the other tables
are actually UPDATED. who's got the clue stick?

--
will@serensoft.com
http://www.dontUthink.com/

Re: can a trigger on insert -> update other tables?

От
brichard@cafod.org.uk (Bruce Richardson)
Дата:
On Fri, Mar 02, 2001 at 03:13:19PM -0600, will trillich wrote:
> i've got a "_rating" table that, when a new record is added,
> i'd like to have propagate through some other tables to update
> running totals:
>
> CREATE FUNCTION _rating_propagate( _rating ) RETURNS OPAQUE AS '

Trigger functions shouldn't have parameters.  And you don't need the NEW
in this line:
>     FOR EACH ROW EXECUTE PROCEDURE _rating_propagate( NEW );

The new variable is automatically made available to the trigger
function.

And remember to do
    RETURN new
somewhere.


--
Bruce

Re: can a trigger on insert -> update other tables?

От
will trillich
Дата:
On Sat, Mar 03, 2001 at 02:08:18PM +0000, Bruce Richardson wrote:
> On Fri, Mar 02, 2001 at 03:13:19PM -0600, will trillich wrote:
> > i've got a "_rating" table that, when a new record is added,
> > i'd like to have propagate through some other tables to update
> > running totals:
> >
> > CREATE FUNCTION _rating_propagate( _rating ) RETURNS OPAQUE AS '
>
> Trigger functions shouldn't have parameters.  And you don't need the NEW
> in this line:
> >     FOR EACH ROW EXECUTE PROCEDURE _rating_propagate( NEW );
>
> The new variable is automatically made available to the trigger
> function.

well that's not something my 7.0.3 posgresql likes, apparently:

CREATE FUNCTION "_rating_propagate" ( ) RETURNS opaque AS '
    DECLARE
        opinion   char(1) := upper(substring(NEW.rating from 1 for 1));
    BEGIN
        IF opinion = ''A'' THEN
-- A == excellent
UPDATE _student SET a = a + 1 WHERE _student.who = NEW.student;
UPDATE _faculty SET a = a + 1 WHERE _faculty.who = NEW.who  AND  _faculty.edu = NEW.edu;

[snippage]

        END IF;
        RETURN NEW;
    END;
' LANGUAGE 'plpgsql';

CREATE TRIGGER _rating_propagate
    BEFORE INSERT ON _rating
    FOR EACH ROW EXECUTE PROCEDURE _rating_propagate();

ERROR: NEW used in non-rule function

(this doesn't happen until an insert actually activates the
trigger, so that plpgsql finally 'sees' the code of the procedure
and tries to execute it.) so what else could i try?

> And remember to do
>     RETURN new
> somewhere.

right. but now i have a different problem... :)

--
It is always hazardous to ask "Why?" in science, but it is often
interesting to do so just the same.
        -- Isaac Asimov, 'The Genetic Code'

will@serensoft.com
http://groups.yahoo.com/group/newbieDoc -- we need your brain!
http://www.dontUthink.com/ -- your brain needs us!

Re: can a trigger on insert -> update other tables?

От
Jan Wieck
Дата:
will trillich wrote:
> [...]
>
> CREATE TRIGGER _rating_propagate
>    BEFORE INSERT ON _rating
>    FOR EACH ROW EXECUTE PROCEDURE _rating_propagate();
>
> ERROR: NEW used in non-rule function
>
> (this doesn't happen until an insert actually activates the
> trigger, so that plpgsql finally 'sees' the code of the procedure
> and tries to execute it.) so what else could i try?
>
> > And remember to do
> >  RETURN new
> > somewhere.
>
> right. but now i have a different problem... :)

    Can you add the line

        #option dump

    at the very top of your function (before DECLARE) and send me
    the debug output from the Postmaster?


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


Re: can a trigger on insert -> update other tables?

От
will trillich
Дата:
On Sun, Mar 04, 2001 at 04:52:16AM -0500, Jan Wieck wrote:
> will trillich wrote:
> > [...]
> >
> > CREATE TRIGGER _rating_propagate
> >    BEFORE INSERT ON _rating
> >    FOR EACH ROW EXECUTE PROCEDURE _rating_propagate();
> >
> > ERROR: NEW used in non-rule function
> >
> > (this doesn't happen until an insert actually activates the
> > trigger, so that plpgsql finally 'sees' the code of the procedure
> > and tries to execute it.) so what else could i try?
> >
> > > And remember to do
> > >  RETURN new
> > > somewhere.
> >
> > right. but now i have a different problem... :)
>
>     Can you add the line
>
>         #option dump
>
>     at the very top of your function (before DECLARE) and send me
>     the debug output from the Postmaster?

sure! if you like, i can post the source SQL for the ratings
table and its views and functions and triggers and rules...

-- begin LOGFILE --

Execution tree of successfully compiled PL/pgSQL function _rating_propagate:

Functions data area:
    entry 0: REC new
    entry 1: REC old
    entry 2: VAR tg_name          type name (typoid 19) atttypmod -1
    entry 3: VAR tg_when          type text (typoid 25) atttypmod -1
    entry 4: VAR tg_level         type text (typoid 25) atttypmod -1
    entry 5: VAR tg_op            type text (typoid 25) atttypmod -1
    entry 6: VAR tg_relid         type oid (typoid 26) atttypmod -1
    entry 7: VAR tg_relname       type name (typoid 19) atttypmod -1
    entry 8: VAR tg_nargs         type int4 (typoid 23) atttypmod -1
    entry 9: VAR found            type bool (typoid 16) atttypmod -1
    entry 10: VAR opinion          type bpchar (typoid 1042) atttypmod 5
    entry 11: VAR courseID         type int4 (typoid 23) atttypmod -1
    entry 12: VAR topicID          type int4 (typoid 23) atttypmod -1
    entry 13: VAR eduID            type int4 (typoid 23) atttypmod -1
    entry 14: VAR profID           type int4 (typoid 23) atttypmod -1
    entry 15: RECFIELD rating           of REC 0
    entry 16: ROW *internal*       fields courseID=var 11
    entry 17: RECFIELD course           of REC 0
    entry 18: ROW *internal*       fields topicID=var 12
    entry 19: ROW *internal*       fields eduID=var 13
    entry 20: ROW *internal*       fields profID=var 14
    entry 21: RECFIELD who              of REC 0
    entry 22: RECFIELD student          of REC 0
    entry 23: RECFIELD who              of REC 0
    entry 24: RECFIELD student          of REC 0
    entry 25: RECFIELD who              of REC 0
    entry 26: RECFIELD student          of REC 0
    entry 27: RECFIELD who              of REC 0
    entry 28: RECFIELD student          of REC 0
    entry 29: RECFIELD who              of REC 0
    entry 30: RECFIELD rating           of REC 0
    entry 31: RECFIELD student          of REC 0
    entry 32: RECFIELD who              of REC 0
    entry 33: RECFIELD who              of REC 0
    entry 34: RECFIELD student          of REC 0

Functions statements:
  8:BLOCK <<*unnamed*>>
  9:  ASSIGN var 10 := 'SELECT  upper(substring( $1  from 1 for 1)) {$1=15}'
 10:  SELECT 'SELECT  _course.id WHERE _course.id =  $1  {$1=17}'
        target = 16 *internal*
 12:  SELECT 'SELECT  _topic.id WHERE _topic.id = _course.topic AND _course.id =  $1  {$1=11}'
        target = 18 *internal*
 14:  SELECT 'SELECT  _edu.id WHERE _edu.id = _topic.edu AND _topic.id =  $1  {$1=12}'
        target = 19 *internal*
 17:  SELECT 'SELECT  _prof.who WHERE _prof.who =  $1  AND _prof.course =  $2  {$1=21, $2=11}'
        target = 20 *internal*
 19:  IF 'SELECT  NOT  $1  {$1=9}' THEN
 20:    RAISE ''Unable to match professor to class, for rating''
      ELSE
      ENDIF
 22:  IF 'SELECT   $1  = 'A' {$1=10}' THEN
 24:    EXECSQL 'UPDATE _course SET a = a + 1 WHERE _course.id =  $1  {$1=11}'
 25:    EXECSQL 'UPDATE _topic SET a = a + 1 WHERE _topic.id =  $1  {$1=12}'
 26:    EXECSQL 'UPDATE _edu SET a = a + 1 WHERE _edu.id =  $1  {$1=13}'
 27:    EXECSQL 'UPDATE _student SET a = a + 1 WHERE _student.who =  $1  {$1=22}'
 28:    EXECSQL 'UPDATE _faculty SET a = a + 1 WHERE _faculty.who =  $1  AND _faculty.edu =  $2  {$1=23, $2=13}'
 29:    EXECSQL 'UPDATE _prof SET a = a + 1 WHERE _prof.who =  $1  AND _prof.course =  $2  {$1=14, $2=11}'
      ELSE
 32:    IF 'SELECT   $1  = 'C' {$1=10}' THEN
 33:      EXECSQL 'UPDATE _course SET c = c + 1 WHERE _course.id =  $1  {$1=11}'
 34:      EXECSQL 'UPDATE _topic SET c = c + 1 WHERE _topic.id =  $1  {$1=12}'
 35:      EXECSQL 'UPDATE _edu SET c = c + 1 WHERE _edu.id =  $1  {$1=13}'
 36:      EXECSQL 'UPDATE _student SET c = c + 1 WHERE _student.who =  $1  {$1=24}'
 37:      EXECSQL 'UPDATE _faculty SET c = c + 1 WHERE _faculty.who =  $1  AND _faculty.edu =  $2  {$1=25, $2=13}'
 38:      EXECSQL 'UPDATE _prof SET c = c + 1 WHERE _prof.who =  $1  AND _prof.course =  $2  {$1=14, $2=11}'
        ELSE
 41:      IF 'SELECT   $1  = 'D' {$1=10}' THEN
 42:        EXECSQL 'UPDATE _course SET d = d + 1 WHERE _course.id =  $1  {$1=11}'
 43: Couldn't open /var/lib/postgres/data/pg_options
010304.13:07:18.501 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "_student"
010304.13:07:18.513 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "_student"
010304.13:07:18.519 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "_course"
010304.13:07:18.533 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "_course"
010304.13:07:18.547 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "_who"
010304.13:07:18.566 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "_who"
010304.13:07:18.577 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "l_rating"
010304.13:07:18.590 [15216] NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "l_rating"
010304.13:07:18.684 [15216] NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index '_rating_pkey' for table
'_rating'
010304.13:07:18.684 [15216] NOTICE:  CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
       EXECSQL 'UPDATE _topic SET d = d + 1 WHERE _topic.id =  $1  {$1=12}'
 44:        EXECSQL 'UPDATE _edu SET d = d + 1 WHERE _edu.id =  $1  {$1=13}'
 45:        EXECSQL 'UPDATE _student SET d = d + 1 WHERE _student.who =  $1  {$1=26}'
 46:        EXECSQL 'UPDATE _faculty SET d = d + 1 WHERE _faculty.who =  $1  AND _faculty.edu =  $2  {$1=27, $2=13}'
 47:        EXECSQL 'UPDATE _prof SET d = d + 1 WHERE _prof.who =  $1  AND _prof.course =  $2  {$1=14, $2=11}'
          ELSE
 50:        IF 'SELECT   $1  = 'F' {$1=10}' THEN
 51:          EXECSQL 'UPDATE _course SET f = f + 1 WHERE _course.id =  $1  {$1=11}'
 52:          EXECSQL 'UPDATE _topic SET f = f + 1 WHERE _topic.id =  $1  {$1=12}'
 53:          EXECSQL 'UPDATE _edu SET f = f + 1 WHERE _edu.id =  $1  {$1=13}'
 54:          EXECSQL 'UPDATE _student SET f = f + 1 WHERE _student.who =  $1  {$1=28}'
 55:          EXECSQL 'UPDATE _faculty SET f = f + 1 WHERE _faculty.who =  $1  AND _faculty.edu =  $2  {$1=29, $2=13}'
 56:          EXECSQL 'UPDATE _prof SET f = f + 1 WHERE _prof.who =  $1  AND _prof.course =  $2  {$1=14, $2=11}'
            ELSE
 58:          ASSIGN var 30 := 'SELECT  'B''
 60:          EXECSQL 'UPDATE _course SET b = b + 1 WHERE _course.id =  $1  {$1=11}'
 61:          EXECSQL 'UPDATE _topic SET b = b + 1 WHERE _topic.id =  $1  {$1=12}'
 62:          EXECSQL 'UPDATE _edu SET b = b + 1 WHERE _edu.id =  $1  {$1=13}'
 63:          EXECSQL 'UPDATE _student SET b = b + 1 WHERE _student.who =  $1  {$1=31}'
 64:          EXECSQL 'UPDATE _faculty SET b = b + 1 WHERE _faculty.who =  $1  AND _faculty.edu =  $2  {$1=32, $2=13}'
 65:          EXECSQL 'UPDATE _prof SET b = b + 1 WHERE _prof.who =  $1  AND _prof.course =  $2  {$1=14, $2=11}'
            ENDIF
          ENDIF
        ENDIF
      ENDIF
 70:  EXECSQL 'delete from trak'
 71:  EXECSQL 'insert into trak values( $1 , $2 , $3 , $4 , $5 ) {$1=13, $2=12, $3=11, $4=33, $5=34}'
 72:  RETURN record 0
    END -- *unnamed*

End of execution tree of function _rating_propagate

-- end LOGFILE --

of course, these tables are intricately related to others not
mentioned here... but i'm hoping you can rub your eyeballs over
this and think to yourself "what a newbie! if he'd only ditch the
clavis and use the frammistat, it'd be so simple..." :)

if so, bring it on!

--
It is always hazardous to ask "Why?" in science, but it is often
interesting to do so just the same.
        -- Isaac Asimov, 'The Genetic Code'

will@serensoft.com
http://groups.yahoo.com/group/newbieDoc -- we need your brain!
http://www.dontUthink.com/ -- your brain needs us!