On Tue, 2006-01-10 at 18:05 -0500, Tom Lane wrote:
> Yeah.  I was envisioning two different approaches: for TupleDesc
> references from long-lived data structures (ie, typcache or relcache)
> just increment or decrement the count when the referencing data
> structure changes.  ResourceOwner would be used for dynamic within-query
> references --- in practice, local variables.  If the reference would
> be forgotten during an elog longjmp then you need a ResourceOwner to
> backstop it, otherwise not.

Ah, I see what you mean. In implementing this, I wasn't sure the best
way to provide these two sorts of TupleDesc references. My first thought
was to add a "use ResourceOwner?" boolean parameter to the routines that
create and destroy references to TupleDescs:

extern TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid,
                                         bool use_resowner);
extern TupleDesc CreateTupleDesc(int natts, bool hasoid,
                                 Form_pg_attribute *attrs,
                                 bool use_resowner);
extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc,
                                     bool use_resowner);
extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc,
                                           bool use_resowner);
extern void IncrTupleDescRefCount(TupleDesc tupdesc,
                                  bool use_resowner);
extern void DecrTupleDescRefCount(TupleDesc tupdesc,
                                  bool use_resowner);

But that requires making *all* the call-sites of these routines care
about whether a ResourceOwner is being used. I think most call-sites
will want to use a ResourceOwner, so that ought to be the default.
Avoiding changing the function signatures also means we don't break a
fairly widely-used API. Instead, how about defining:

extern void IncrTupleDescPersistentRefCount(TupleDesc tdesc);

(the name could do with improvement). This would increment the
TupleDesc's "persistent reference count" -- that is, non-persistent
references are automatically released at transaction end, whereas
persistent ones are only released via:

extern void DecrTupleDescPersistentRefCount(TupleDesc tdesc);

One downside is that creating a new, persistent TupleDesc requires a
little pain:

TupleDesc tdesc = make_your_tdesc();

That means we will unnecessarily inform the ResourceOwner about the
TupleDesc, and then tell it to immediately forget about it. However, I
think that's acceptable: ResourceOwnerRememberTupleDesc() is trivial,
and ResourceOwnerForgetTupleDesc() searches beginning at the
most-recently-added TupleDesc, so it should also be very cheap.


---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
       choose an index scan if your joining column's datatypes do not

Reply via email to