Re: [GENERAL] Trigger problems/questions - Mailing list pgsql-general

From Adrian Klaver
Subject Re: [GENERAL] Trigger problems/questions
Date
Msg-id 09274b63-a246-aac1-845f-c8d54e671066@aklaver.com
Whole thread Raw
In response to [GENERAL] Trigger problems/questions  (Jim Fulton <jim@jimfulton.info>)
Responses Re: [GENERAL] Trigger problems/questions  (Jim Fulton <jim@jimfulton.info>)
List pgsql-general
On 06/15/2017 10:23 AM, Jim Fulton wrote:
> I have an object database that's mirrored to a table with data in a
> JSONB column.  Data are organized into "communities".  Community ids
> aren't stored directly in content but can be found by recursively
> following __parent__ properties. I want to be able to index content
> records on their community ids.
>
> (I originally tried to index functions that got ids, but apparently
> lying about immutability is a bad idea and I suffered the consequences. :-])
>
> I tried creating a trigger to populate a community_zoid property with a
> community id when a record is inserted or updated.  The trigger calls a
> recursive functions to get the community id.
>
> Trigger:
> https://github.com/karlproject/karl/blob/master/karl/scripts/pgevolve.py#L261
> <https://github.com/karlproject/karl/blob/master/karl/scripts/pgevolve.py#L261>
>
> Trigger procedure:
> https://github.com/karlproject/karl/blob/master/karl/scripts/pgevolve.py#L236
> <https://github.com/karlproject/karl/blob/master/karl/scripts/pgevolve.py#L236>
>
> Function to find a community id:
> https://github.com/karlproject/karl/blob/master/karl/scripts/pgevolve.py#L209
> <https://github.com/karlproject/karl/blob/master/karl/scripts/pgevolve.py#L209>
>
> This scheme succeeds most of the time, but occasionally, it fails.
>
> I can find records where it has failed with a query like:
>
>    select zoid
>    from newt
>    where find_community_zoid(zoid, class_name, state) is not null
>      and not state ? 'community_zoid';
>
> If I update the records where it has failed:
>
>    update newt set class_name=class_name
>    where find_community_zoid(zoid, class_name, state) is not null
>       and not state ? 'community_zoid';
>
> Then retry the query above, I get 0 rows back. This would seem to
> indicate that the trigger is logically correct.
>
> Questions:
>
>   * Am I doing it wrong?  For example, is there some limitation on
>     trigger procedures that I'm violating?
>   * If a trigger procedure errors, is the transaction aborted? (I would
>     hope so.)
>   * Should I expect triggers to be reliable and rely on them for
>     database integrity?
>   * Any suggestions on how to debug this?

I do not pretend to fully understand what the the triggers/functions are
really doing, but I did notice this:

create or replace function populate_community_zoid_triggerf()

...

new_zoid := NEW.state ->> 'community_zoid';
zoid := find_community_zoid(
             NEW.zoid, NEW.class_name, NEW.state)::text;
if zoid is null then
     if new_zoid is not null then
     NEW.state := NEW.state - 'community_zoid';
     end if;
else
     if new_zoid is null or zoid != new_zoid then
     NEW.state :=
         NEW.state || ('{"community_zoid": ' || zoid || '}')::jsonb;
     end if;
end if;

...


Not sure what happens if zoid is null and new_zoid is null also?
Or if it matters?


>
> Jim
>
> --
> Jim Fulton
> http://jimfulton.info


--
Adrian Klaver
adrian.klaver@aklaver.com


pgsql-general by date:

Previous
From: Paul Lavoie
Date:
Subject: Re: [GENERAL] CREATE FOREIGN TABLE difficulties
Next
From: Tom Lane
Date:
Subject: Re: [GENERAL] Trigger problems/questions