I am trying to create a trigger function in Postgres 13 that, before an insert or update operation is done, will copy values from two columns to two other columns.
Before an update/insert operation my table test.run_conf looks like this:
| hostname | run_config_current | run_config_current_hash | run_config_last | run_config_last_hash |
|---|---|---|---|---|
| switch01 | old_txt_str | 32314322 |
When an update/insert occurs I want the value from run_config_current copied to run_config_last and run_config_current_hash copied to run_config_last_hash. Then allow the update/insert operation to occur against column run_config_current - after which the trigger function will recalculate the value for run_config_current_hash.
For testing, I run the following query to insert new data into the column run_config_current:
INSERT INTO test.run_conf (hostname, run_config_current) VALUES ('switch01', 'new_txt_str' )
ON CONFLICT (hostname) DO UPDATE SET run_config_current = excluded.run_config_current
However what happens is the table test.run_conf gets updated as follows - the new value gets inserted into both columns run_config_current and run_config_last:
| hostname | run_config_current | run_config_current_hash | run_config_last | run_config_last_hash |
|---|---|---|---|---|
| switch01 | new_txt_str | 47173234 | new_txt_str | 32314322 |
The trigger and function I have in place now that is not working properly is:
CREATE OR REPLACE FUNCTION test.run_conf_hash_gen_func()
RETURNS TRIGGER
SET SCHEMA 'test'
LANGUAGE plpgsql
AS $$
BEGIN
NEW.run_config_last := NEW.run_config_current;
NEW.run_config_last_hash := NEW.run_config_current_hash;
NEW.run_config_current_hash := MD5(NEW.run_config_current);
RETURN NEW;
END;
$$
CREATE TRIGGER run_conf_hash_gen_trig
BEFORE INSERT OR UPDATE on test.run_conf
FOR EACH ROW
EXECUTE PROCEDURE test.run_conf_hash_gen_func();
Please help me to understand why my code seems to be copying the new value for run_config_current into run_config_last. Thank you!
OLD.run_config_currentwhen doing theUPDATE. This means that in the trigger function you will need to distinguish between andINSERTorUPDATEasINSERTdoes not haveOLDvalues. SeeTG_OPhere plpgsql trigger function.OLDforINSERTis set toNULLso you do not have to guard against the pre-11 behavior ofOLDbeing unassigned in anINSERT.