aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/catcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/catcache.c')
-rw-r--r--src/backend/utils/cache/catcache.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 0b27bc034c0..bca544fe96f 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -17,6 +17,7 @@
#include "access/genam.h"
#include "access/hash.h"
#include "access/heapam.h"
+#include "access/tuptoaster.h"
#include "access/valid.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
@@ -1634,16 +1635,32 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
uint32 hashValue, Index hashIndex, bool negative)
{
CatCTup *ct;
+ HeapTuple dtp;
MemoryContext oldcxt;
/*
+ * If there are any out-of-line toasted fields in the tuple, expand them
+ * in-line. This saves cycles during later use of the catcache entry,
+ * and also protects us against the possibility of the toast tuples being
+ * freed before we attempt to fetch them, in case of something using a
+ * slightly stale catcache entry.
+ */
+ if (HeapTupleHasExternal(ntp))
+ dtp = toast_flatten_tuple(ntp, cache->cc_tupdesc);
+ else
+ dtp = ntp;
+
+ /*
* Allocate CatCTup header in cache memory, and copy the tuple there too.
*/
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
ct = (CatCTup *) palloc(sizeof(CatCTup));
- heap_copytuple_with_tuple(ntp, &ct->tuple);
+ heap_copytuple_with_tuple(dtp, &ct->tuple);
MemoryContextSwitchTo(oldcxt);
+ if (dtp != ntp)
+ heap_freetuple(dtp);
+
/*
* Finish initializing the CatCTup header, and add it to the cache's
* linked list and counts.