On Wed, May 27, 2015 at 12:07 PM, hubert depesz lubaczewski <
dep...@depesz.com> wrote:

> On Wed, May 27, 2015 at 01:55:24PM +0300, Jordan Gigov wrote:
> > Updating a materialized view in my case. It should only update when 2-3
> of
> > our 30+ tables get new data, which for those is kind of rare. Not having
> > such a trigger means I will have to call it in each usage in the code and
> > hope future maintainers don't forget it. This is why I postponed
> migrating
> > the one search query where materialized views would be useful, because
> it's
> > heavy.
>
> Add daemon which runs "LISTEN", and triggers on the underlying tables
> that do NOTIFY.
> When daemon picks something from LISTEN (which happens only after
> commit) - it can do anything that needs to be done, and it will not
> block the transaction, which is an added benefit.
>
> depesz
>
>
You can also emulate once per transaction on commit triggers by a
combination of an
after trigger and a temporary table.

-- Deferred constraint triggers run when the transaction are commited

-- BUT they can only be declared AFTER ROW !  And having many of them

-- can be quiet expensive.

-- Normal triggers are pretty cheap but cannot be deferred

-- So we indirect via an additional table so that per one transaction

-- we issue only one run of the trigger



create unlogged table schedule_work_at_end_of_transaction(b bool);



create function work_at_end_of_transaction() returns trigger language
plpgsql as $$
begin

  delete from schedule_work_at_end_of_transaction;

  raise notice 'trigger!';

  return NEW;

end ;

$$ ;



create constraint trigger work_at_end_of_transaction after insert

  on schedule_work_at_end_of_transaction

  initially deferred for each row

  execute procedure work_at_end_of_transaction();



create table test(t text);



create function schedule_if_necessary() returns trigger language plpgsql as
$$
begin

  if not exists (select null from schedule_work_at_end_of_transaction limit
1) then
    insert into schedule_work_at_end_of_transaction values(true);

  end if;

  return NEW;

end;

$$ ;





begin;

  do $$

    begin

      for i in 1..1000 loop

        insert into test select s :: text from generate_series(1, 1000) s;

      end loop;

    end ;

  $$ ;

commit;

truncate test;



create trigger schedule_if_necessary after insert or update on test

  for each statement

  execute procedure schedule_if_necessary();



begin;

  do $$

    begin

      for i in 1..1000 loop

        insert into test select s :: text from generate_series(1, 1000) s;

      end loop;

    end ;

  $$ ;

commit;



drop table test;

drop table schedule_work_at_end_of_transaction;

drop function schedule_if_necessary();

drop function work_at_end_of_transaction();


>

Reply via email to