Wiki instructions for creating insert trigger for PostgreSQL are wrong wiki.dovecot.org/Quota/Dict Calling INSERT on the table from within BEFORE INSERT trigger creates cascading trigger. postgresql.org/docs/current/interactive/trigger-definition.html Instead, one should return NEW record from the trigger, and it will be inserted after trigger execution. --- CREATE OR REPLACE FUNCTION merge_quota2() RETURNS TRIGGER AS $$ BEGIN IF NEW.messages < 0 OR NEW.messages IS NULL THEN -- ugly kludge: we came here from this function, really do try to insert IF NEW.messages IS NULL THEN NEW.messages = 0; ELSE NEW.messages = -NEW.messages; END IF; return NEW; END IF; LOOP UPDATE quota2 SET bytes = bytes + NEW.bytes, messages = messages + NEW.messages WHERE username = NEW.username; IF found THEN RETURN NULL; END IF; BEGIN IF NEW.messages = 0 THEN RETURN NEW; ELSE NEW.messages = - NEW.messages; RETURN NEW; END IF; EXCEPTION WHEN unique_violation THEN -- someone just inserted the record, update it END; END LOOP; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS mergequota2 ON quota2; CREATE TRIGGER mergequota2 BEFORE INSERT ON quota2 FOR EACH ROW EXECUTE PROCEDURE merge_quota2(); --- Best regards, Adis
On Thu, 2011-12-15 at 09:37 +0100, Adis Nezirovic wrote:> Wiki instructions for creating insert trigger for PostgreSQL are wrong > wiki.dovecot.org/Quota/Dict > > Calling INSERT on the table from within BEFORE INSERT trigger creates > cascading trigger.Yes..> Instead, one should return NEW record from the trigger, and it will be > inserted after trigger execution.But does this handle race conditions when a record is inserted/deleted while the trigger is being run? That's the reason this trigger is so complex.> BEGIN > IF NEW.messages = 0 THEN > RETURN NEW; > ELSE > NEW.messages = - NEW.messages; > RETURN NEW; > END IF; > EXCEPTION WHEN unique_violation THEN > -- someone just inserted the record, update it > END;I'd guess the unique_violation is never caught here, and instead the whole INSERT fails?