1/*-------------------------------------------------------------------------
4 * An implementation of DestReceiver that stores the result tuples in
7 * Optionally, we can force detoasting (but not decompression) of out-of-line
8 * toasted values. This is to support cursors WITH HOLD, which must retain
9 * data even if the underlying table is dropped.
11 * Also optionally, we can apply a tuple conversion map before storing.
14 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
18 * src/backend/executor/tstoreReceiver.c
20 *-------------------------------------------------------------------------
37 bool detoast;
/* were we told to detoast? */
54 * Prepare to receive tuples from executor.
60 bool needtoast =
false;
61 int natts = typeinfo->
natts;
64 /* Check if any columns require detoast work */
67 for (
i = 0;
i < natts;
i++)
81 /* Check if tuple conversion is needed */
89 /* Set up appropriate callback */
94 /* Create workspace */
119 * Receive a tuple from the executor and store it in the tuplestore.
120 * This is for the easy case where we don't have to detoast nor map anything.
133 * Receive a tuple from the executor and store it in the tuplestore.
134 * This is for the case where we have to detoast any toasted values.
141 int natts = typeinfo->
natts;
146 /* Make sure the tuple is fully deconstructed */
150 * Fetch back any out-of-line datums. We build the new datums array in
151 * myState->outvalues[] (but we can re-use the slot's isnull array). Also,
152 * remember the fetched values to free afterwards.
155 for (
i = 0;
i < natts;
i++)
174 * Push the modified tuple into the tuplestore.
181 /* And release any temporary detoasted values */
182 for (
i = 0;
i < nfree;
i++)
189 * Receive a tuple from the executor and store it in the tuplestore.
190 * This is for the case where we must apply a tuple conversion map.
204 * Clean up at end of an executor run
211 /* Release workspace if any */
227 * Destroy receiver when done with it
236 * Initially create a DestReceiver object.
249 /* private fields will be set by SetTuplestoreDestReceiverParams */
255 * Set parameters for a TuplestoreDestReceiver
257 * tStore: where to store the tuples
258 * tContext: memory context containing tStore
259 * detoast: forcibly detoast contained data?
260 * target_tupdesc: if not NULL, forcibly convert tuples to this rowtype
261 * map_failure_msg: error message to use if mapping to target_tupdesc fails
263 * We don't currently support both detoast and target_tupdesc at the same
264 * time, just because no existing caller needs that combination.
272 const char *map_failure_msg)
276 Assert(!(detoast && target_tupdesc));
280 myState->
cxt = tContext;
struct varlena * detoast_external_attr(struct varlena *attr)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsVirtual
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Assert(PointerIsAligned(start, uint64))
void * MemoryContextAlloc(MemoryContext context, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
const char * map_failure_msg
TupleConversionMap * tupmap
TupleDesc tts_tupleDescriptor
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
void(* rShutdown)(DestReceiver *self)
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
void(* rDestroy)(DestReceiver *self)
static bool tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
DestReceiver * CreateTuplestoreDestReceiver(void)
static bool tstoreReceiveSlot_tupmap(TupleTableSlot *slot, DestReceiver *self)
static void tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
static void tstoreShutdownReceiver(DestReceiver *self)
void SetTuplestoreDestReceiverParams(DestReceiver *self, Tuplestorestate *tStore, MemoryContext tContext, bool detoast, TupleDesc target_tupdesc, const char *map_failure_msg)
static void tstoreDestroyReceiver(DestReceiver *self)
static bool tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
void free_conversion_map(TupleConversionMap *map)
TupleConversionMap * convert_tuples_by_position(TupleDesc indesc, TupleDesc outdesc, const char *msg)
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
static void slot_getallattrs(TupleTableSlot *slot)
static bool VARATT_IS_EXTERNAL(const void *PTR)