summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane2006-06-16 18:42:24 +0000
committerTom Lane2006-06-16 18:42:24 +0000
commit06e10abc0bb4297a0754313b4f158bdd5622ca24 (patch)
tree6d413dfdfab3fea4a6d96b07b7fdb8ba81498860 /src/include
parentb49ce32da1975b2fdab26e463b7189b95e770809 (diff)
Fix problems with cached tuple descriptors disappearing while still in use
by creating a reference-count mechanism, similar to what we did a long time ago for catcache entries. The back branches have an ugly solution involving lots of extra copies, but this way is more efficient. Reference counting is only applied to tupdescs that are actually in caches --- there seems no need to use it for tupdescs that are generated in the executor, since they'll go away during plan shutdown by virtue of being in the per-query memory context. Neil Conway and Tom Lane
Diffstat (limited to 'src/include')
-rw-r--r--src/include/access/tupdesc.h26
-rw-r--r--src/include/executor/executor.h8
-rw-r--r--src/include/executor/tuptable.h19
-rw-r--r--src/include/utils/resowner.h10
-rw-r--r--src/include/utils/typcache.h6
5 files changed, 52 insertions, 17 deletions
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index 670ef5c92e0..035a0a85e52 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/tupdesc.h,v 1.49 2006/03/16 00:31:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/tupdesc.h,v 1.50 2006/06/16 18:42:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,6 +57,14 @@ typedef struct tupleConstr
* tdtypeid is RECORDOID, and tdtypmod can be either -1 for a fully anonymous
* row type, or a value >= 0 to allow the rowtype to be looked up in the
* typcache.c type cache.
+ *
+ * Tuple descriptors that live in caches (relcache or typcache, at present)
+ * are reference-counted: they can be deleted when their reference count goes
+ * to zero. Tuple descriptors created by the executor need no reference
+ * counting, however: they are simply created in the appropriate memory
+ * context and go away when the context is freed. We set the tdrefcount
+ * field of such a descriptor to -1, while reference-counted descriptors
+ * always have tdrefcount >= 0.
*/
typedef struct tupleDesc
{
@@ -67,6 +75,7 @@ typedef struct tupleDesc
Oid tdtypeid; /* composite type ID for tuple type */
int32 tdtypmod; /* typmod for tuple type */
bool tdhasoid; /* tuple has oid attribute in its header */
+ int tdrefcount; /* reference count, or -1 if not counting */
} *TupleDesc;
@@ -81,6 +90,21 @@ extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc);
extern void FreeTupleDesc(TupleDesc tupdesc);
+extern void IncrTupleDescRefCount(TupleDesc tupdesc);
+extern void DecrTupleDescRefCount(TupleDesc tupdesc);
+
+#define PinTupleDesc(tupdesc) \
+ do { \
+ if ((tupdesc)->tdrefcount >= 0) \
+ IncrTupleDescRefCount(tupdesc); \
+ } while (0)
+
+#define ReleaseTupleDesc(tupdesc) \
+ do { \
+ if ((tupdesc)->tdrefcount >= 0) \
+ DecrTupleDescRefCount(tupdesc); \
+ } while (0)
+
extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
extern void TupleDescInitEntry(TupleDesc desc,
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index a29e1394974..d926d8b5c5c 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.126 2006/03/05 15:58:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.127 2006/06/16 18:42:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -249,8 +249,7 @@ extern ExprContext *MakePerTupleExprContext(EState *estate);
} while (0)
extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
-extern void ExecAssignResultType(PlanState *planstate,
- TupleDesc tupDesc, bool shouldFree);
+extern void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc);
extern void ExecAssignResultTypeFromTL(PlanState *planstate);
extern TupleDesc ExecGetResultType(PlanState *planstate);
extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList,
@@ -259,8 +258,7 @@ extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList,
extern void ExecAssignProjectionInfo(PlanState *planstate);
extern void ExecFreeExprContext(PlanState *planstate);
extern TupleDesc ExecGetScanType(ScanState *scanstate);
-extern void ExecAssignScanType(ScanState *scanstate,
- TupleDesc tupDesc, bool shouldFree);
+extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
extern void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate);
extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 1b2eb883ecf..b506651fbbd 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.30 2006/03/05 15:58:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.31 2006/06/16 18:42:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -15,6 +15,7 @@
#define TUPTABLE_H
#include "access/htup.h"
+#include "access/tupdesc.h"
/*----------
@@ -56,13 +57,17 @@
* TRUE, tts_shouldFree FALSE, tts_tuple NULL, tts_buffer InvalidBuffer,
* and tts_nvalid zero.
*
+ * The tupleDescriptor is simply referenced, not copied, by the TupleTableSlot
+ * code. The caller of ExecSetSlotDescriptor() is responsible for providing
+ * a descriptor that will live as long as the slot does. (Typically, both
+ * slots and descriptors are in per-query memory and are freed by memory
+ * context deallocation at query end; so it's not worth providing any extra
+ * mechanism to do more. However, the slot will increment the tupdesc
+ * reference count if a reference-counted tupdesc is supplied.)
+ *
* When tts_shouldFree is true, the physical tuple is "owned" by the slot
* and should be freed when the slot's reference to the tuple is dropped.
*
- * tts_shouldFreeDesc is similar to tts_shouldFree: if it's true, then the
- * tupleDescriptor is "owned" by the TupleTableSlot and should be
- * freed when the slot's reference to the descriptor is dropped.
- *
* If tts_buffer is not InvalidBuffer, then the slot is holding a pin
* on the indicated buffer page; drop the pin when we release the
* slot's reference to that buffer. (tts_shouldFree should always be
@@ -87,7 +92,6 @@ typedef struct TupleTableSlot
NodeTag type; /* vestigial ... allows IsA tests */
bool tts_isempty; /* true = slot is empty */
bool tts_shouldFree; /* should pfree tuple? */
- bool tts_shouldFreeDesc; /* should pfree descriptor? */
bool tts_slow; /* saved state for slot_deform_tuple */
HeapTuple tts_tuple; /* physical tuple, or NULL if none */
TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */
@@ -124,8 +128,7 @@ extern void ExecDropTupleTable(TupleTable table, bool shouldFree);
extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
extern TupleTableSlot *ExecAllocTableSlot(TupleTable table);
-extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
- TupleDesc tupdesc, bool shouldFree);
+extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
TupleTableSlot *slot,
Buffer buffer,
diff --git a/src/include/utils/resowner.h b/src/include/utils/resowner.h
index 4e69f844a7e..9c8b91670b1 100644
--- a/src/include/utils/resowner.h
+++ b/src/include/utils/resowner.h
@@ -12,13 +12,14 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/resowner.h,v 1.6 2006/03/05 15:59:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/resowner.h,v 1.7 2006/06/16 18:42:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef RESOWNER_H
#define RESOWNER_H
+#include "access/tupdesc.h"
#include "storage/buf.h"
#include "utils/catcache.h"
#include "utils/rel.h"
@@ -107,4 +108,11 @@ extern void ResourceOwnerRememberRelationRef(ResourceOwner owner,
extern void ResourceOwnerForgetRelationRef(ResourceOwner owner,
Relation rel);
+/* support for tupledesc refcount management */
+extern void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner);
+extern void ResourceOwnerRememberTupleDesc(ResourceOwner owner,
+ TupleDesc tupdesc);
+extern void ResourceOwnerForgetTupleDesc(ResourceOwner owner,
+ TupleDesc tupdesc);
+
#endif /* RESOWNER_H */
diff --git a/src/include/utils/typcache.h b/src/include/utils/typcache.h
index cbb13be3255..7d3e284871c 100644
--- a/src/include/utils/typcache.h
+++ b/src/include/utils/typcache.h
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/typcache.h,v 1.10 2006/03/05 15:59:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/typcache.h,v 1.11 2006/06/16 18:42:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,7 +58,7 @@ typedef struct TypeCacheEntry
/*
* Tuple descriptor if it's a composite type (row type). NULL if not
* composite or information hasn't yet been requested. (NOTE: this is
- * actually just a link to information maintained by relcache.c.)
+ * a reference-counted tupledesc.)
*/
TupleDesc tupDesc;
} TypeCacheEntry;
@@ -79,6 +79,8 @@ extern TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod);
extern TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod,
bool noError);
+extern TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod);
+
extern void assign_record_type_typmod(TupleDesc tupDesc);
extern void flush_rowtype_cache(Oid type_id);