PostgreSQL Source Code: src/backend/executor/tstoreReceiver.c Source File

PostgreSQL Source Code git master
tstoreReceiver.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * tstoreReceiver.c
4 * An implementation of DestReceiver that stores the result tuples in
5 * a Tuplestore.
6 *
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.
10 *
11 * Also optionally, we can apply a tuple conversion map before storing.
12 *
13 *
14 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
16 *
17 * IDENTIFICATION
18 * src/backend/executor/tstoreReceiver.c
19 *
20 *-------------------------------------------------------------------------
21 */
22
23#include "postgres.h"
24
25#include "access/detoast.h"
26#include "access/tupconvert.h"
27#include "executor/tstoreReceiver.h"
28#include "varatt.h"
29
30
31 typedef struct
32{
33 DestReceiver pub;
34 /* parameters: */
35 Tuplestorestate *tstore; /* where to put the data */
36 MemoryContext cxt; /* context containing tstore */
37 bool detoast; /* were we told to detoast? */
38 TupleDesc target_tupdesc; /* target tupdesc, or NULL if none */
39 const char *map_failure_msg; /* tupdesc mapping failure message */
40 /* workspace: */
41 Datum *outvalues; /* values array for result tuple */
42 Datum *tofree; /* temp values to be pfree'd */
43 TupleConversionMap *tupmap; /* conversion map, if needed */
44 TupleTableSlot *mapslot; /* slot for mapped tuples */
45} TStoreState;
46
47
48static bool tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self);
49static bool tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self);
50static bool tstoreReceiveSlot_tupmap(TupleTableSlot *slot, DestReceiver *self);
51
52
53/*
54 * Prepare to receive tuples from executor.
55 */
56static void
57 tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
58{
59 TStoreState *myState = (TStoreState *) self;
60 bool needtoast = false;
61 int natts = typeinfo->natts;
62 int i;
63
64 /* Check if any columns require detoast work */
65 if (myState->detoast)
66 {
67 for (i = 0; i < natts; i++)
68 {
69 CompactAttribute *attr = TupleDescCompactAttr(typeinfo, i);
70
71 if (attr->attisdropped)
72 continue;
73 if (attr->attlen == -1)
74 {
75 needtoast = true;
76 break;
77 }
78 }
79 }
80
81 /* Check if tuple conversion is needed */
82 if (myState->target_tupdesc)
83 myState->tupmap = convert_tuples_by_position(typeinfo,
84 myState->target_tupdesc,
85 myState->map_failure_msg);
86 else
87 myState->tupmap = NULL;
88
89 /* Set up appropriate callback */
90 if (needtoast)
91 {
92 Assert(!myState->tupmap);
93 myState->pub.receiveSlot = tstoreReceiveSlot_detoast;
94 /* Create workspace */
95 myState->outvalues = (Datum *)
96 MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
97 myState->tofree = (Datum *)
98 MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
99 myState->mapslot = NULL;
100 }
101 else if (myState->tupmap)
102 {
103 myState->pub.receiveSlot = tstoreReceiveSlot_tupmap;
104 myState->outvalues = NULL;
105 myState->tofree = NULL;
106 myState->mapslot = MakeSingleTupleTableSlot(myState->target_tupdesc,
107 &TTSOpsVirtual);
108 }
109 else
110 {
111 myState->pub.receiveSlot = tstoreReceiveSlot_notoast;
112 myState->outvalues = NULL;
113 myState->tofree = NULL;
114 myState->mapslot = NULL;
115 }
116}
117
118/*
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.
121 */
122static bool
123 tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
124{
125 TStoreState *myState = (TStoreState *) self;
126
127 tuplestore_puttupleslot(myState->tstore, slot);
128
129 return true;
130}
131
132/*
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.
135 */
136static bool
137 tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
138{
139 TStoreState *myState = (TStoreState *) self;
140 TupleDesc typeinfo = slot->tts_tupleDescriptor;
141 int natts = typeinfo->natts;
142 int nfree;
143 int i;
144 MemoryContext oldcxt;
145
146 /* Make sure the tuple is fully deconstructed */
147 slot_getallattrs(slot);
148
149 /*
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.
153 */
154 nfree = 0;
155 for (i = 0; i < natts; i++)
156 {
157 Datum val = slot->tts_values[i];
158 CompactAttribute *attr = TupleDescCompactAttr(typeinfo, i);
159
160 if (!attr->attisdropped && attr->attlen == -1 && !slot->tts_isnull[i])
161 {
162 if (VARATT_IS_EXTERNAL(DatumGetPointer(val)))
163 {
164 val = PointerGetDatum(detoast_external_attr((struct varlena *)
165 DatumGetPointer(val)));
166 myState->tofree[nfree++] = val;
167 }
168 }
169
170 myState->outvalues[i] = val;
171 }
172
173 /*
174 * Push the modified tuple into the tuplestore.
175 */
176 oldcxt = MemoryContextSwitchTo(myState->cxt);
177 tuplestore_putvalues(myState->tstore, typeinfo,
178 myState->outvalues, slot->tts_isnull);
179 MemoryContextSwitchTo(oldcxt);
180
181 /* And release any temporary detoasted values */
182 for (i = 0; i < nfree; i++)
183 pfree(DatumGetPointer(myState->tofree[i]));
184
185 return true;
186}
187
188/*
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.
191 */
192static bool
193 tstoreReceiveSlot_tupmap(TupleTableSlot *slot, DestReceiver *self)
194{
195 TStoreState *myState = (TStoreState *) self;
196
197 execute_attr_map_slot(myState->tupmap->attrMap, slot, myState->mapslot);
198 tuplestore_puttupleslot(myState->tstore, myState->mapslot);
199
200 return true;
201}
202
203/*
204 * Clean up at end of an executor run
205 */
206static void
207 tstoreShutdownReceiver(DestReceiver *self)
208{
209 TStoreState *myState = (TStoreState *) self;
210
211 /* Release workspace if any */
212 if (myState->outvalues)
213 pfree(myState->outvalues);
214 myState->outvalues = NULL;
215 if (myState->tofree)
216 pfree(myState->tofree);
217 myState->tofree = NULL;
218 if (myState->tupmap)
219 free_conversion_map(myState->tupmap);
220 myState->tupmap = NULL;
221 if (myState->mapslot)
222 ExecDropSingleTupleTableSlot(myState->mapslot);
223 myState->mapslot = NULL;
224}
225
226/*
227 * Destroy receiver when done with it
228 */
229static void
230 tstoreDestroyReceiver(DestReceiver *self)
231{
232 pfree(self);
233}
234
235/*
236 * Initially create a DestReceiver object.
237 */
238DestReceiver *
239 CreateTuplestoreDestReceiver(void)
240{
241 TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
242
243 self->pub.receiveSlot = tstoreReceiveSlot_notoast; /* might change */
244 self->pub.rStartup = tstoreStartupReceiver;
245 self->pub.rShutdown = tstoreShutdownReceiver;
246 self->pub.rDestroy = tstoreDestroyReceiver;
247 self->pub.mydest = DestTuplestore;
248
249 /* private fields will be set by SetTuplestoreDestReceiverParams */
250
251 return (DestReceiver *) self;
252}
253
254/*
255 * Set parameters for a TuplestoreDestReceiver
256 *
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
262 *
263 * We don't currently support both detoast and target_tupdesc at the same
264 * time, just because no existing caller needs that combination.
265 */
266void
267 SetTuplestoreDestReceiverParams(DestReceiver *self,
268 Tuplestorestate *tStore,
269 MemoryContext tContext,
270 bool detoast,
271 TupleDesc target_tupdesc,
272 const char *map_failure_msg)
273{
274 TStoreState *myState = (TStoreState *) self;
275
276 Assert(!(detoast && target_tupdesc));
277
278 Assert(myState->pub.mydest == DestTuplestore);
279 myState->tstore = tStore;
280 myState->cxt = tContext;
281 myState->detoast = detoast;
282 myState->target_tupdesc = target_tupdesc;
283 myState->map_failure_msg = map_failure_msg;
284}
@ DestTuplestore
Definition: dest.h:93
struct varlena * detoast_external_attr(struct varlena *attr)
Definition: detoast.c:45
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1427
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1443
Assert(PointerIsAligned(start, uint64))
long val
Definition: informix.c:689
i
int i
Definition: isn.c:77
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
bool attisdropped
Definition: tupdesc.h:77
int16 attlen
Definition: tupdesc.h:71
Tuplestorestate * tstore
Definition: tstoreReceiver.c:35
MemoryContext cxt
Definition: tstoreReceiver.c:36
const char * map_failure_msg
Definition: tstoreReceiver.c:39
TupleTableSlot * mapslot
Definition: tstoreReceiver.c:44
Datum * tofree
Definition: tstoreReceiver.c:42
TupleDesc target_tupdesc
Definition: tstoreReceiver.c:38
DestReceiver pub
Definition: tstoreReceiver.c:33
TupleConversionMap * tupmap
Definition: tstoreReceiver.c:43
Datum * outvalues
Definition: tstoreReceiver.c:41
bool detoast
Definition: tstoreReceiver.c:37
AttrMap * attrMap
Definition: tupconvert.h:28
int natts
Definition: tupdesc.h:137
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:122
bool * tts_isnull
Definition: tuptable.h:126
Datum * tts_values
Definition: tuptable.h:124
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
CommandDest mydest
Definition: dest.h:128
Definition: c.h:692
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)
Definition: tstoreReceiver.c:57
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)
Definition: tupconvert.c:300
TupleConversionMap * convert_tuples_by_position(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:60
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:193
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:175
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:742
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:371
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition: varatt.h:354

AltStyle によって変換されたページ (->オリジナル) /