Return-Path: pg_adm@postgres.berkeley.edu
Received: by postgres.Berkeley.EDU (5.61/1.29)
	id AA25108; Fri, 2 Apr 93 00:26:22 -0800
Date: Fri, 2 Apr 93 00:26:22 -0800
Message-Id: <9304020826.AA25108@postgres.Berkeley.EDU>
From: mcquaig!postgres@uunet.UU.NET (Postgres System User)
Subject: big dumps from rewrites
To: postgres@postgres.berkeley.edu
Sender: pg_adm@postgres.berkeley.edu


I certainly don't know if the problem I found is common.  However, I
have discovered at least one way to cause the 70meg dumps discussed
recently.  If rewrite rules fall into a circular logic, postgres will
happily keep applying the same rules to themselves until it dies.  I
had one instance such a follows:

define rewrite rule r1 is
on append to c1
do [ append c2 ... ] 

define rewrite rule r2 is
on replace to c1
do [ replace c2 ... ]

define rewrite rule r3 is
on append to c2 where such and such1
do [ replace c1 ... ]

Where such and such1 is a qualifier that should control the feedback.
However, in rewrite rules the qualifiers are really flaky and don't
seem to be tested before the rule is rewritten into the query.  The
same scheme above does work on instance level rules.  However, you
can't seem to get a much rule down under instance rules as you can
with rewrite rules before pg says sorry to big!  It may however also
be true that the scheme works with instance rules because I increment
the command counter after firing each rule so that the results of all
predecessors are visible to each successive rule as it triggers.  Not
stock I know but more useful in my environment.

The deadly loop above occurs in RewriteHandler.c(QueryRewrite).  It is
actually quite spectacular to watch it get pregnant an explode.
Talk about robust. I had to watch, my poor 486 stopped everything else
while was happening.  A little short on cpu cycles perhaps ;-}

On perhaps a more productive note I found what I believe to be an
error in prs2append.c(prs2Append).  

In prs2append.c(prs2Append) about line 211 is the following:

    if (status == PRS2_STATUS_TUPLE_CHANGED) {
	if (prs2GetNumberOfLocks(newLocks) == 0) {
	    prs2FreeLocks(newLocks);
	    return(PRS2_STATUS_TUPLE_CHANGED);
	} else {
!/* XXX nmm005 	    
! *          HeapTupleSetRuleLock(*returnedTupleP, InvalidBuffer,newLocks); 
! *
! * In attributeValueMakeNewTuple() (actually heap_modifytuple()), the 
! * rulelock is bcopy'd in from 'tuple' which was created outside 
! * of this memory context and gets pfreed upstream!
! * HeapTupleSetRuleLock() pfrees the old lock in *returnedTupleP,
! * that's twice resulting in an error caught in portalmem.c:
! * NOTICE:Mar 30 12:38:45:PortalHeapMemoryFree: 0x8198424 not in alloc set!
! * This of course issues a SIGHUP and aborts whatever was going on.
! * There also seems to be a memory leak somewhere! I thought those
! * were gone?!# in early v3.
! */
+	    (*returnedTupleP)->t_locktype = MEM_RULE_LOCK;
+	    (*returnedTupleP)->t_lock.l_lock = newLocks;
	    return(PRS2_STATUS_TUPLE_CHANGED);
	}

I doubt if this is the best way to fix it but at the moment it was the
most expedient.  It really should be in rac.c with the rest of the
stuff I guess.  

nmm

PS. If someone comes up with a pregnancy fix for the 70meg dumps,
please send a copy.  I must either fix it or rewrite the app. ugh!
If there is a more appropriate place to discuss this kind of techo-babble,
please advise.  I don't wish to annoy the uninterested or look really 
dumb when I'm wrong!  Are the bug fixes at postgres.berkeley.edu ever
made available anymore on an as found basis?
Thanks again for the bandwidth.


Neil M. McQuaig      344 Millicent Way,  Shreveport, LA  71106
VOICE: (318)868-5611 UUCP: mcquaig!nmm (318)861-1051 or uunet!mcquaig!nmm
