Thread: Problems with NEW.* in triggers

Problems with NEW.* in triggers

From
Jamie Lawrence
Date:
Hi folks -

I'm having a problem with what looks like it should be trivial.

For the function

create or replace function timestamp_fn() returns opaque as '       begin       NEW.moddate := coalesce(NEW.moddate,
now());      return NEW;       end
 
' language 'plpgsql';

on an after insert or update trigger, never sets moddate to now().

I had thought that if moddate isn't included in an insert or update,
that it would be null in the NEW context, so that this would fall 
through to the now() call. (I also tried this as below:

create or replace function timestamp_fn() returns opaque as '    begin    if NEW.moddate is not null then
returnNEW;    else            NEW.moddate := now();            return NEW;    end if;     end
 
' language 'plpgsql';

With the same results.)

Any thoughts on what I'm doing wrong??

-j


-- 
Jamie Lawrence                                        jal@jal.org
Never eat anything bigger than your head.




Re: Problems with NEW.* in triggers

From
Tom Lane
Date:
Jamie Lawrence <postgres@jal.org> writes:
> I had thought that if moddate isn't included in an insert or update,
> that it would be null in the NEW context,

No, it would be whatever the value to be assigned to the column would
be, if the trigger were not present.  In particular, during an UPDATE
it's going to contain the old value of the field.  In an INSERT it would
be whatever the column's default value is.

I am not sure what your intention is here.  If you want the trigger to
force the field to current time, it can certainly do that.  If you want
the user to control whether the field is updated, why do you need a
trigger at all?
        regards, tom lane


Re: Problems with NEW.* in triggers

From
Josh Berkus
Date:
Jamie,

> Any thoughts on what I'm doing wrong??

Yes.  If you want to modify the new data, you need to use a BEFORE trigger.
AFTER triggers can't modify NEW, just read it.

--
-Josh BerkusAglio Database SolutionsSan Francisco



Re: Problems with NEW.* in triggers

From
Jamie Lawrence
Date:
On Tue, 04 Nov 2003, Tom Lane wrote:

> Jamie Lawrence <postgres@jal.org> writes:
> > I had thought that if moddate isn't included in an insert or update,
> > that it would be null in the NEW context,
> 
> No, it would be whatever the value to be assigned to the column would
> be, if the trigger were not present.  In particular, during an UPDATE
> it's going to contain the old value of the field.  In an INSERT it would
> be whatever the column's default value is.

For an insert, the default is null in this case.

test=# create table trash (moddate timestamp, message text);
CREATE TABLE
test=# create or replace function timestamp_test() returns opaque as '
test'#         begin
test'#         NEW.moddate := coalesce(NEW.moddate, now());
test'#         return NEW;
test'#         end
test'# ' language 'plpgsql';
CREATE FUNCTION
test=# create trigger critter_timestamp_test after insert or update on critter for each row execute procedure
timestamp_fn();
CREATE TRIGGER
test=# insert into trash (message) values ('hi there');
INSERT 560920 1
test=# insert into trash (message) values ('hi there');
INSERT 560921 1
test=# select * from trash;moddate | message  
---------+----------        | hi there        | hi there
(2 rows)

test=# 

I don't understand why moddate isn't getting set to now() in the above.

(Point taken on updates... I was thinking about NEW in slightly
the wrong way for an after trigger.)


> I am not sure what your intention is here.  If you want the trigger to
> force the field to current time, it can certainly do that.  If you want
> the user to control whether the field is updated, why do you need a
> trigger at all?

Excellent question, sigh. I'm trying to bandaid a bad design choice
until the application can be changed.

Now that you have me thinking about it, an update rule is probably a
better idea.

Thanks for the help, I appreciate it -

-j


-- 
Jamie Lawrence                                        jal@jal.org
"Remember, half-measures can be very effective if all you deal with are
half-wits."  - Chris Klein




Re: Problems with NEW.* in triggers

From
Tom Lane
Date:
Jamie Lawrence <postgres@jal.org> writes:
> I don't understand why moddate isn't getting set to now() in the above.

Josh fingered the problem there --- you need a BEFORE trigger if you
want to affect the data that will be stored.  I had missed that little
mistake :-(
        regards, tom lane


Re: Problems with NEW.* in triggers

From
Jamie Lawrence
Date:
On Tue, 04 Nov 2003, Tom Lane wrote:

> Jamie Lawrence <postgres@jal.org> writes:
> > I don't understand why moddate isn't getting set to now() in the above.
> 
> Josh fingered the problem there --- you need a BEFORE trigger if you
> want to affect the data that will be stored.  I had missed that little
> mistake :-(

Yep. Many thanks to both of you.

-j


-- 
Jamie Lawrence                                        jal@jal.org
If built in great numbers, motels will be used for nothing but illegal
purposes.   - J. Edgar Hoover