sqlpostgresqltriggerspostgresql-10postgresql-triggers

Setting NEW.column in "before update" trigger sets values from previous trigger call


I'm trying to create a before update trigger for a table. Basically, on each row update I need to set additional column on the same row on the same table.

However, for some reason, each trigger call results in setting values from a previous trigger call.

Here's the code for my trigger:

create or replace function test_trigger_func() returns trigger as $$
    declare
        v_department  text;
    begin
        select department.name into v_department
        from salesprofile
        left join (
           select department.name from salesprofile join department on department.id = (
               salesprofile.solutionscreteria #>> '{departments, 0}'
           )::int4 where salesprofile.id = NEW.id
        ) department on true
        where salesprofile.id = NEW.id
        group by department.name;
        
        NEW.department = v_department;
        
        raise notice 'DEP: %', v_department;
        raise notice 'NEW DEP: %', NEW.department;
        
        return NEW;
    end;
$$ language plpgsql;

drop trigger if exists test_trigger on salesprofile;

create trigger test_trigger before update on salesprofile
for each row execute procedure test_trigger_func();

The select statement inside the test_trigger_func function works correctly when run outside the function. But the raise notice statements show incorrect (previous) values when the select is called from inside the test_trigger_func function.

The salesprofile.solutionscreteria #>> '{departments, 0}' statement contains the id for the row in the department table. And I'm trying to set the department column on the salesprofile table row from the "department".name on each salesprofile row update (by modifying NEW.department = ...).


The behaviour I get:


I don't get how and why this is happening and I do hope I'm explaining the behaviour in an intelligible way.

Is this the expected behaviour for potgresql triggers? If not, then could you explain what's happening and how to make it work correctly?


Solution

  • It is a BEFORE trigger so it occurs before the salesprofile table has the NEW data. I'm not entirely following but I'm go to say that this salesprofile.solutionscreteria #>> '{departments, 0}' is using the existing(previous) row not the update data the trigger is running on. Try it with NEW.solutionscreteria.