Thread: Using a trigger with an object-relational manager

Using a trigger with an object-relational manager

From
Rick Schumeyer
Date:
I'm using Ruby on Rails and have two tables, A and B.  Every row in A
needs a corresponding row in B.  A also contains a FK pointing to B.

I created a before insert trigger on A that inserts a new row in B, and
sets the FK in A.  This seems to be running fine.

The problem is that the new A object that rails gets does not see the
effect of the trigger.  If I call the "reload" method, then everything
is ok.

I'm not sure if this is a rails specific problem, or if there is an
adjustment I can make to my SQL to avoid the need for the reload.

Can I somehow put the creation of A, B and setting the FK in a
transaction so that rails receives the row from A after the trigger
completes?  If so, I'm not sure the best way to do that.

Thanks for any suggestions!

Re: Using a trigger with an object-relational manager

From
Michael Glaesemann
Date:
On May 22, 2007, at 21:21 , Rick Schumeyer wrote:

> The problem is that the new A object that rails gets does not see
> the effect of the trigger.  If I call the "reload" method, then
> everything is ok.

As ActiveRecord (which I'm assuming you're using with Rails) has no
idea of what is going on in the database (ActiveRecord doesn't have a
concept of triggers), there's no way for it to see the effect of the
trigger without querying the database for the latest information
(which is what you're doing with reload).

Michael Glaesemann
grzm seespotcode net



Re: Using a trigger with an object-relational manager

From
PFC
Date:
> I'm using Ruby on Rails and have two tables, A and B.  Every row in A
> needs a corresponding row in B.  A also contains a FK pointing to B.
>
> I created a before insert trigger on A that inserts a new row in B, and
> sets the FK in A.  This seems to be running fine.

    So, A has a b_id field linking to B ?

    If you need a 1-1 relationship, you could try instead to use the same
primary key in B than in A :

A : id SERIAL PRIMARY KEY
B : id INTEGER PRIMARY KEY (not SERIAL)

Then, AFTER INSERT trigger on A checks the value the sequence put in A.id
and inserts in B with this value as the PK.

    Postgres has INSERT ... RETURNING which is a very clean and elegant
solution but Rails never heard about it...




Re: Using a trigger with an object-relational manager

From
PFC
Date:
On Wed, 23 May 2007 14:41:00 +0200, Rick Schumeyer <rschumeyer@ieee.org>
wrote:

> Actually, the situation is slightly more complicated.  It's more like I
> have tables A1, A2, and A3 each of which must have a corresponding row
> in B.  So each of A1, A2 and A3 has a BEFORE INSERT trigger that creates
> a row in B and sets a FK in A1 (or A2 or A3).  So I can't just use the
> same PK in both the A tables and B.

    It's a hack, but A1, A2, A3 etc could all use the same sequence to
generate their PK...

    The best would be to patch rails so it uses INSERT RETURNING.

Re: Using a trigger with an object-relational manager

From
Rick Schumeyer
Date:
I just realized that I was having a slight brain-freeze earlier.
ActiveRecord creates an A object first, then tells pg to INSERT it, but
nothing is actually returned by the INSERT statement.  (I assume that
Hibernate et. al would be the same).  So of course it does not see the
result of the trigger, since it does not receive a result from the
database...until reload is called.

At least I assume that is correct.
Michael Glaesemann wrote:
>
> On May 22, 2007, at 21:21 , Rick Schumeyer wrote:
>
>> The problem is that the new A object that rails gets does not see the
>> effect of the trigger.  If I call the "reload" method, then
>> everything is ok.
>
> As ActiveRecord (which I'm assuming you're using with Rails) has no
> idea of what is going on in the database (ActiveRecord doesn't have a
> concept of triggers), there's no way for it to see the effect of the
> trigger without querying the database for the latest information
> (which is what you're doing with reload).
>
> Michael Glaesemann
> grzm seespotcode net


Re: Using a trigger with an object-relational manager

From
Rick Schumeyer
Date:
Actually, the situation is slightly more complicated.  It's more like I
have tables A1, A2, and A3 each of which must have a corresponding row
in B.  So each of A1, A2 and A3 has a BEFORE INSERT trigger that creates
a row in B and sets a FK in A1 (or A2 or A3).  So I can't just use the
same PK in both the A tables and B.

PFC wrote:
>
>> I'm using Ruby on Rails and have two tables, A and B.  Every row in A
>> needs a corresponding row in B.  A also contains a FK pointing to B.
>>
>> I created a before insert trigger on A that inserts a new row in B,
>> and sets the FK in A.  This seems to be running fine.
>
>     So, A has a b_id field linking to B ?
>
>     If you need a 1-1 relationship, you could try instead to use the
> same primary key in B than in A :
>
> A : id SERIAL PRIMARY KEY
> B : id INTEGER PRIMARY KEY (not SERIAL)
>
> Then, AFTER INSERT trigger on A checks the value the sequence put in
> A.id and inserts in B with this value as the PK.
>
>     Postgres has INSERT ... RETURNING which is a very clean and
> elegant solution but Rails never heard about it...