agora inbox for pgsql-sql@postgresql.org  
help / color / mirror / Atom feed
From: Martin Edlman <martin.edlman@gmail.com>
To: pgsql-sql@postgresql.org
Subject: Bug or feature in AFTER INSERT trigger?
Date: Wed, 05 Nov 2014 14:00:21 +0100
Message-ID: <545A1F65.6050705@gmail.com> (raw)
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-sql>

Hello,

today I encountered strange behaviour in PgSQL 9.0 (tried in 9.3 with
same effect).

There is a table and an AFTER INSERT trigger which call a function which
counts a number of records in the same table. But the newly inserted
record is not selected and counted.

When I delete a record and the very same AFTER trigger calls the very
same function, selected and counted records are already without the
deleted one.

I supposed that after insert the record is already in the database,
isn't it true?!

The documentation doesn't mention this. (or I didn't find it).

Can someone confirm it as a bug or explain why it works this way.

Regards,
Martin Edlman



EXAMPLE:

-- FUNCTION

CREATE OR REPLACE FUNCTION tmp.email_service(contrid integer)
  RETURNS integer AS
$BODY$
DECLARE
	sid  integer := 119;
	rec  record;
	vfrom date;
	vto date;
	cmnt text;
	cnt integer := 0;
BEGIN
	vfrom := date_trunc('month', now());
	vto := date_trunc('month', now() + interval '1 month') - interval '1 day';
	RAISE NOTICE 'sid %, from %, to %', sid, vfrom, vto;
	FOR rec IN
		SELECT ma.contract_id, count(ma.*) as unitage, string_agg(ma.email, ',
' order by ma.email) as emails
		FROM tmp.mail_account as ma
		WHERE contract_id = contrid
		AND coalesce(ma.valid_from, '-infinity') < now()
		AND coalesce(ma.valid_to, 'infinity') > now()
		GROUP BY 1
	LOOP
		RAISE NOTICE 'number of mails: %, mails: %', rec.unitage, rec.emails;
		cnt := cnt + 1;
		-- here is some code which inserts or updates
		-- services ...
	END LOOP;
	RETURN cnt;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION tmp.email_service(integer)
  OWNER TO postgres;
GRANT EXECUTE ON FUNCTION tmp.email_service(integer) TO public;
GRANT EXECUTE ON FUNCTION tmp.email_service(integer) TO postgres;




-- TRIGGER FUNCTION
CREATE OR REPLACE FUNCTION tmp.email_service()
  RETURNS trigger AS
$BODY$
BEGIN
	IF TG_OP = 'INSERT' THEN
		RAISE NOTICE '% % email %@% inserted, setting services for id %',
TG_WHEN, TG_OP, NEW.username, NEW.domain, NEW.contract_id;
		-- call a function
		PERFORM tmp.email_service(NEW.contract_id);
		RETURN NEW;
	END IF;

	IF TG_OP = 'UPDATE' THEN
		--
		RETURN NEW;
	END IF;

	IF TG_OP = 'DELETE' THEN
		PERFORM tmp.email_service(OLD.contract_id);
		RETURN OLD;
	END IF;

	RETURN NULL;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION tmp.email_service()
  OWNER TO edlman;
GRANT EXECUTE ON FUNCTION tmp.email_service() TO public;
GRANT EXECUTE ON FUNCTION tmp.email_service() TO edlman;




-- TABLE
CREATE TABLE tmp.mail_account
(
  id serial NOT NULL,
  contract_id integer NOT NULL,
  username character varying(50) NOT NULL,
  domain character varying(100) NOT NULL,
  email character varying(255) NOT NULL,
  valid_from timestamp without time zone DEFAULT now(),
  valid_to timestamp without time zone,
  CONSTRAINT mail_account_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tmp.mail_account OWNER TO postgres;

CREATE UNIQUE INDEX mail_account_email
  ON tmp.mail_account
  USING btree
  (email COLLATE pg_catalog."default");
CREATE UNIQUE INDEX mail_account_email_idx
  ON tmp.mail_account
  USING btree
  (username COLLATE pg_catalog."default", domain COLLATE
pg_catalog."default");
CREATE INDEX mail_account_username_idx
  ON tmp.mail_account
  USING btree
  (username COLLATE pg_catalog."default");
CREATE TRIGGER email_service
  AFTER INSERT OR UPDATE OR DELETE
  ON tmp.mail_account
  FOR EACH ROW
  EXECUTE PROCEDURE tmp.email_service();



-- 
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql



view thread (2+ messages)  latest in thread

Message-ID: <545A1F65.6050705@gmail.com>
Permalink:  ../545A1F65.6050705@gmail.com/
Also on:    postgresql.org/message-id/545A1F65.6050705@gmail.com

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-sql@postgresql.org
  Cc: martin.edlman@gmail.com
  Subject: Re: Bug or feature in AFTER INSERT trigger?
  In-Reply-To: <545A1F65.6050705@gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox