Thread: RelationFlushRelation() or RelationClearRelation()

RelationFlushRelation() or RelationClearRelation()

From
Brent Verner
Date:
Hi,
 I've almost got the ALTER TABLE RENAME fixed so it doesn't break
triggers referring to the renamed column.  The final problem is that
after the pg_trigger.tgargs is updated, that change is not visible 
in the current backend.  I see that there are a couple of interesting
functions to refresh the RelationCache:
 RelationClearRelation(Relation, bool);
 RelationFlushRelation(Relation);

Which one of these should I use to have the new pg_trigger data visible
in the current backend?  Or is there a better way than either of these?

I should be able to clean up this work and send a patch tomorrow 
evening if I get this kink worked out.

Thanks, Brent

-- 
"Develop your talent, man, and leave the world something. Records are 
really gifts from people. To think that an artist would love you enough
to share his music with anyone is a beautiful thing."  -- Duane Allman


Re: RelationFlushRelation() or RelationClearRelation()

From
Tom Lane
Date:
Brent Verner <brent@rcfile.org> writes:
>   I've almost got the ALTER TABLE RENAME fixed so it doesn't break
> triggers referring to the renamed column.  The final problem is that
> after the pg_trigger.tgargs is updated, that change is not visible 
> in the current backend.

This should happen automatically as a consequence of the relcache flush
message.  Doing a manual RelationClearRelation or whatever is NOT the
answer; if you find yourself doing that, it means that other backends
aren't hearing about the change either.

The usual way to force a relcache flush is to update the relation's
pg_class row.  Now that I think about it, I'm not sure ALTER TABLE
RENAME COLUMN would have any direct reason to do that, so it may be
broken already in this regard.  Does the relcache entry's column
data get updated with the new name?
        regards, tom lane


Re: RelationFlushRelation() or RelationClearRelation()

From
Brent Verner
Date:
On 06 Nov 2001 at 14:54 (-0500), Tom Lane wrote:
| Brent Verner <brent@rcfile.org> writes:
| >   I've almost got the ALTER TABLE RENAME fixed so it doesn't break
| > triggers referring to the renamed column.  The final problem is that
| > after the pg_trigger.tgargs is updated, that change is not visible 
| > in the current backend.
| 
| This should happen automatically as a consequence of the relcache flush
| message.  Doing a manual RelationClearRelation or whatever is NOT the
| answer; if you find yourself doing that, it means that other backends
| aren't hearing about the change either.

gotcha. I don't know what you mean by 'relcache flush message,' but
I'll figure that out soon ;-)

| The usual way to force a relcache flush is to update the relation's
| pg_class row.  Now that I think about it, I'm not sure ALTER TABLE
| RENAME COLUMN would have any direct reason to do that, so it may be
| broken already in this regard.  Does the relcache entry's column
| data get updated with the new name?

The relation->triggerdesc still has the old tgargs after updating the
pg_trigger table, so the triggered RI_ function is called with the
old arguments.

It is probably noteworthy that I am directly modifying the tgargs
in the pg_trigger table, via simple_heap_update().  This modfication
is made at the end of renameatt() in rename.c.  Could making this
change prior to the column rename cause the 'relcache flush message' 
to do the right thing?  [I'm going to try this as soon as I'm off work.]

Also, is directly updating the pg_trigger table advisable?  I'll
look further at trigger.c to see if I overlooked any utility to do
this cleaner.

cheers. brent

-- 
"Develop your talent, man, and leave the world something. Records are 
really gifts from people. To think that an artist would love you enough
to share his music with anyone is a beautiful thing."  -- Duane Allman


Re: RelationFlushRelation() or RelationClearRelation()

From
Tom Lane
Date:
Brent Verner <brent@rcfile.org> writes:
> It is probably noteworthy that I am directly modifying the tgargs
> in the pg_trigger table, via simple_heap_update().  This modfication
> is made at the end of renameatt() in rename.

Seems reasonable.

Now that I think about it, the problem is almost certainly that the
relcache+sinval mechanism isn't recognizing this update as requiring
relcache-entry rebuild.  If you update a pg_class row, it definitely
does recognize that event as forcing relcache rebuild, and I had thought
that updating a pg_attribute row associated with a relcache entry would
cause one too.  But maybe not.  We should either extend the sinval code
to make that happen, or tweak renameatt to force a relcache flush
explicitly.

Alternatively, maybe you're expecting too much?  The relcache rebuild
doesn't (and isn't supposed to) happen until the next transaction commit
or CommandCounterIncrement.  If you've structured the code in a way that
needs the relcache change to happen sooner, then I think we need to find
a way to avoid expecting that to happen.

> Also, is directly updating the pg_trigger table advisable?

simple_heap_update seems pretty direct to me :-) ... what did you have
in mind?
        regards, tom lane


Re: RelationFlushRelation() or RelationClearRelation()

From
Tom Lane
Date:
I said:
> Now that I think about it, the problem is almost certainly that the
> relcache+sinval mechanism isn't recognizing this update as requiring
> relcache-entry rebuild.  If you update a pg_class row, it definitely
> does recognize that event as forcing relcache rebuild, and I had thought
> that updating a pg_attribute row associated with a relcache entry would
> cause one too.  But maybe not.

It sure looks to me like the update of the pg_attribute row
should be sufficient to queue a relcache flush message (see
RelationInvalidateHeapTuple and subsidiary routines in
backend/utils/cache/inval.c).  We could argue about whether
PrepareForTupleInvalidation needs to test for a wider variety of
relcache-invalidating updates, but nonetheless I don't see why
renameatt would be failing to trigger one.  Are you sure it's
not working?
        regards, tom lane


Re: RelationFlushRelation() or RelationClearRelation()

From
Tom Lane
Date:
Brent Verner <brent@rcfile.org> writes:
> After running the above and without (re)starting a new backend yields
> the following error.  After getting a new backend, the behavior is as 
> desired.

>   brent=# insert into child values(1);
>   ERROR:  constraint <unnamed>: table parent does not have an attribute id

I wonder whether you're looking in the right place.  The RI trigger code
caches query plans --- could that caching be the source of the problem?
(See backend/utils/adt/ri_triggers.c)
        regards, tom lane


Re: RelationFlushRelation() or RelationClearRelation()

From
Brent Verner
Date:
On 06 Nov 2001 at 19:08 (-0500), Tom Lane wrote:
| I said:
| > Now that I think about it, the problem is almost certainly that the
| > relcache+sinval mechanism isn't recognizing this update as requiring
| > relcache-entry rebuild.  If you update a pg_class row, it definitely
| > does recognize that event as forcing relcache rebuild, and I had thought
| > that updating a pg_attribute row associated with a relcache entry would
| > cause one too.  But maybe not.
| 
| It sure looks to me like the update of the pg_attribute row
| should be sufficient to queue a relcache flush message (see
| RelationInvalidateHeapTuple and subsidiary routines in
| backend/utils/cache/inval.c).  We could argue about whether
| PrepareForTupleInvalidation needs to test for a wider variety of
| relcache-invalidating updates, but nonetheless I don't see why
| renameatt would be failing to trigger one.  Are you sure it's
| not working?

Pretty darned sure that I've accurately described my symptoms.
Doing the tgargs update before or after the actual column update
did not affect the behavior -- the cached relation->triggerdesc
still contains incorrect tgargs.  I'll clean up what I have and 
post a patch for review.

To reply to your earlier email asking what do I expect.

I'd like to be able to say...
 brent# create table parent (id int UNIQUE); brent# create table child (id int4 references parent(id) on update
cascade);brent# alter table parent RENAME id to hello; brent# insert into parent values (1); brent# insert into child
values(1);
 

After running the above and without (re)starting a new backend yields
the following error.  After getting a new backend, the behavior is as 
desired.
 brent=# insert into child values(1); ERROR:  constraint <unnamed>: table parent does not have an attribute id
 brent=# select tgargs from pg_trigger;                              tgargs
----------------------------------------------------------------
<unnamed>\000child\000parent\000UNSPECIFIED\000id\000hello\000
<unnamed>\000child\000parent\000UNSPECIFIED\000id\000hello\000
<unnamed>\000child\000parent\000UNSPECIFIED\000id\000hello\000


Your comments on this matter have been much appreciated.  I'll next
look (further) into the sinval mechanism for a way to forcibly 
invalidate the cached relation->triggerdesc.
 Brent

-- 
"Develop your talent, man, and leave the world something. Records are 
really gifts from people. To think that an artist would love you enough
to share his music with anyone is a beautiful thing."  -- Duane Allman


Re: RelationFlushRelation() or RelationClearRelation()

From
Brent Verner
Date:
On 06 Nov 2001 at 23:57 (-0500), Tom Lane wrote:
| Brent Verner <brent@rcfile.org> writes:
| > After running the above and without (re)starting a new backend yields
| > the following error.  After getting a new backend, the behavior is as 
| > desired.
| 
| >   brent=# insert into child values(1);
| >   ERROR:  constraint <unnamed>: table parent does not have an attribute id
| 
| I wonder whether you're looking in the right place.  The RI trigger code
| caches query plans --- could that caching be the source of the problem?
| (See backend/utils/adt/ri_triggers.c)

Tom,
 This code is now working as desired.  I believe the problem I was
seeing was due to my incorrect (and STUPID) approach to modifying
the bytea pg_trigger->tgargs directly...  I've since learned about 
heap_modifytuple().  Anyway, I'm cleaning this patch up, and  will 
be sending it to -patches shortly.
 Thanks for your assistance with this, and hopefully the next time I 
decide to hack at PG, I'll choose something a bit more my speed :-P

cheers. Brent

-- 
"Develop your talent, man, and leave the world something. Records are 
really gifts from people. To think that an artist would love you enough
to share his music with anyone is a beautiful thing."  -- Duane Allman


Re: RelationFlushRelation() or RelationClearRelation()

From
Tom Lane
Date:
Brent Verner <brent@rcfile.org> writes:
>   Thanks for your assistance with this, and hopefully the next time I 
> decide to hack at PG, I'll choose something a bit more my speed :-P

Sounds like "your speed" has advanced a couple notches.  Hang in there
... how do you think the rest of us learned?  ;-)
        regards, tom lane


Re: RelationFlushRelation() or RelationClearRelation()

From
Brent Verner
Date:
On 09 Nov 2001 at 23:41 (-0500), Tom Lane wrote:
| Brent Verner <brent@rcfile.org> writes:
| >   Thanks for your assistance with this, and hopefully the next time I 
| > decide to hack at PG, I'll choose something a bit more my speed :-P
| 
| Sounds like "your speed" has advanced a couple notches.  Hang in there
| ... how do you think the rest of us learned?  ;-)

I sure hope it didn't hurt anyone elses head as much as it hurts mine.
My initial 'success' was sheer luck.  In testing, I noticed certain
length column names would do the wrong thing... Turns out I had to
malloc the struct varlena* so it was padded to account for the size
of the attached vl_dat data, to keep vl_dat from stepping all over
the place... oh, /that's/ why I like perl ;-)

cheers. brent

-- 
"Develop your talent, man, and leave the world something. Records are 
really gifts from people. To think that an artist would love you enough
to share his music with anyone is a beautiful thing."  -- Duane Allman


Re: RelationFlushRelation() or RelationClearRelation()

From
Bruce Momjian
Date:
> On 09 Nov 2001 at 23:41 (-0500), Tom Lane wrote:
> | Brent Verner <brent@rcfile.org> writes:
> | >   Thanks for your assistance with this, and hopefully the next time I 
> | > decide to hack at PG, I'll choose something a bit more my speed :-P
> | 
> | Sounds like "your speed" has advanced a couple notches.  Hang in there
> | ... how do you think the rest of us learned?  ;-)
> 
> I sure hope it didn't hurt anyone elses head as much as it hurts mine.

When I see those long function names in subject lines, I hope Tom Lane
takes the topic because I used to have to struggle though answering
those type of questions.  I makes everyone's head hurt, but it's good
for you.  :-)

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026