Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * execTuples.c
4 : * Routines dealing with TupleTableSlots. These are used for resource
5 : * management associated with tuples (eg, releasing buffer pins for
6 : * tuples in disk buffers, or freeing the memory occupied by transient
7 : * tuples). Slots also provide access abstraction that lets us implement
8 : * "virtual" tuples to reduce data-copying overhead.
9 : *
10 : * Routines dealing with the type information for tuples. Currently,
11 : * the type information for a tuple is an array of FormData_pg_attribute.
12 : * This information is needed by routines manipulating tuples
13 : * (getattribute, formtuple, etc.).
14 : *
15 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
16 : * Portions Copyright (c) 1994, Regents of the University of California
17 : *
18 : *
19 : * IDENTIFICATION
20 : * src/backend/executor/execTuples.c
21 : *
22 : *-------------------------------------------------------------------------
23 : */
24 : /*
25 : * INTERFACE ROUTINES
26 : *
27 : * SLOT CREATION/DESTRUCTION
28 : * MakeTupleTableSlot - create an empty slot
29 : * ExecAllocTableSlot - create a slot within a tuple table
30 : * ExecResetTupleTable - clear and optionally delete a tuple table
31 : * MakeSingleTupleTableSlot - make a standalone slot, set its descriptor
32 : * ExecDropSingleTupleTableSlot - destroy a standalone slot
33 : *
34 : * SLOT ACCESSORS
35 : * ExecSetSlotDescriptor - set a slot's tuple descriptor
36 : * ExecStoreTuple - store a physical tuple in the slot
37 : * ExecStoreMinimalTuple - store a minimal physical tuple in the slot
38 : * ExecClearTuple - clear contents of a slot
39 : * ExecStoreVirtualTuple - mark slot as containing a virtual tuple
40 : * ExecCopySlotTuple - build a physical tuple from a slot
41 : * ExecCopySlotMinimalTuple - build a minimal physical tuple from a slot
42 : * ExecMaterializeSlot - convert virtual to physical storage
43 : * ExecCopySlot - copy one slot's contents to another
44 : *
45 : * CONVENIENCE INITIALIZATION ROUTINES
46 : * ExecInitResultTupleSlot \ convenience routines to initialize
47 : * ExecInitScanTupleSlot \ the various tuple slots for nodes
48 : * ExecInitExtraTupleSlot / which store copies of tuples.
49 : * ExecInitNullTupleSlot /
50 : *
51 : * Routines that probably belong somewhere else:
52 : * ExecTypeFromTL - form a TupleDesc from a target list
53 : *
54 : * EXAMPLE OF HOW TABLE ROUTINES WORK
55 : * Suppose we have a query such as SELECT emp.name FROM emp and we have
56 : * a single SeqScan node in the query plan.
57 : *
58 : * At ExecutorStart()
59 : * ----------------
60 : * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
61 : * ExecInitResultTupleSlot() to construct TupleTableSlots
62 : * for the tuples returned by the access methods and the
63 : * tuples resulting from performing target list projections.
64 : *
65 : * During ExecutorRun()
66 : * ----------------
67 : * - SeqNext() calls ExecStoreTuple() to place the tuple returned
68 : * by the access methods into the scan tuple slot.
69 : *
70 : * - ExecSeqScan() calls ExecStoreTuple() to take the result
71 : * tuple from ExecProject() and place it into the result tuple slot.
72 : *
73 : * - ExecutePlan() calls the output function.
74 : *
75 : * The important thing to watch in the executor code is how pointers
76 : * to the slots containing tuples are passed instead of the tuples
77 : * themselves. This facilitates the communication of related information
78 : * (such as whether or not a tuple should be pfreed, what buffer contains
79 : * this tuple, the tuple's tuple descriptor, etc). It also allows us
80 : * to avoid physically constructing projection tuples in many cases.
81 : */
82 : #include "postgres.h"
83 :
84 : #include "access/htup_details.h"
85 : #include "access/tuptoaster.h"
86 : #include "funcapi.h"
87 : #include "catalog/pg_type.h"
88 : #include "nodes/nodeFuncs.h"
89 : #include "storage/bufmgr.h"
90 : #include "utils/builtins.h"
91 : #include "utils/lsyscache.h"
92 : #include "utils/typcache.h"
93 :
94 :
95 : static TupleDesc ExecTypeFromTLInternal(List *targetList,
96 : bool hasoid, bool skipjunk);
97 :
98 :
99 : /* ----------------------------------------------------------------
100 : * tuple table create/delete functions
101 : * ----------------------------------------------------------------
102 : */
103 :
104 : /* --------------------------------
105 : * MakeTupleTableSlot
106 : *
107 : * Basic routine to make an empty TupleTableSlot.
108 : * --------------------------------
109 : */
110 : TupleTableSlot *
111 167314 : MakeTupleTableSlot(void)
112 : {
113 167314 : TupleTableSlot *slot = makeNode(TupleTableSlot);
114 :
115 167314 : slot->tts_isempty = true;
116 167314 : slot->tts_shouldFree = false;
117 167314 : slot->tts_shouldFreeMin = false;
118 167314 : slot->tts_tuple = NULL;
119 167314 : slot->tts_tupleDescriptor = NULL;
120 167314 : slot->tts_mcxt = CurrentMemoryContext;
121 167314 : slot->tts_buffer = InvalidBuffer;
122 167314 : slot->tts_nvalid = 0;
123 167314 : slot->tts_values = NULL;
124 167314 : slot->tts_isnull = NULL;
125 167314 : slot->tts_mintuple = NULL;
126 :
127 167314 : return slot;
128 : }
129 :
130 : /* --------------------------------
131 : * ExecAllocTableSlot
132 : *
133 : * Create a tuple table slot within a tuple table (which is just a List).
134 : * --------------------------------
135 : */
136 : TupleTableSlot *
137 94599 : ExecAllocTableSlot(List **tupleTable)
138 : {
139 94599 : TupleTableSlot *slot = MakeTupleTableSlot();
140 :
141 94599 : *tupleTable = lappend(*tupleTable, slot);
142 :
143 94599 : return slot;
144 : }
145 :
146 : /* --------------------------------
147 : * ExecResetTupleTable
148 : *
149 : * This releases any resources (buffer pins, tupdesc refcounts)
150 : * held by the tuple table, and optionally releases the memory
151 : * occupied by the tuple table data structure.
152 : * It is expected that this routine be called by EndPlan().
153 : * --------------------------------
154 : */
155 : void
156 21414 : ExecResetTupleTable(List *tupleTable, /* tuple table */
157 : bool shouldFree) /* true if we should free memory */
158 : {
159 : ListCell *lc;
160 :
161 111370 : foreach(lc, tupleTable)
162 : {
163 89956 : TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);
164 :
165 : /* Always release resources and reset the slot to empty */
166 89956 : ExecClearTuple(slot);
167 89956 : if (slot->tts_tupleDescriptor)
168 : {
169 83464 : ReleaseTupleDesc(slot->tts_tupleDescriptor);
170 83464 : slot->tts_tupleDescriptor = NULL;
171 : }
172 :
173 : /* If shouldFree, release memory occupied by the slot itself */
174 89956 : if (shouldFree)
175 : {
176 0 : if (slot->tts_values)
177 0 : pfree(slot->tts_values);
178 0 : if (slot->tts_isnull)
179 0 : pfree(slot->tts_isnull);
180 0 : pfree(slot);
181 : }
182 : }
183 :
184 : /* If shouldFree, release the list structure */
185 21414 : if (shouldFree)
186 0 : list_free(tupleTable);
187 21414 : }
188 :
189 : /* --------------------------------
190 : * MakeSingleTupleTableSlot
191 : *
192 : * This is a convenience routine for operations that need a
193 : * standalone TupleTableSlot not gotten from the main executor
194 : * tuple table. It makes a single slot and initializes it
195 : * to use the given tuple descriptor.
196 : * --------------------------------
197 : */
198 : TupleTableSlot *
199 72646 : MakeSingleTupleTableSlot(TupleDesc tupdesc)
200 : {
201 72646 : TupleTableSlot *slot = MakeTupleTableSlot();
202 :
203 72646 : ExecSetSlotDescriptor(slot, tupdesc);
204 :
205 72646 : return slot;
206 : }
207 :
208 : /* --------------------------------
209 : * ExecDropSingleTupleTableSlot
210 : *
211 : * Release a TupleTableSlot made with MakeSingleTupleTableSlot.
212 : * DON'T use this on a slot that's part of a tuple table list!
213 : * --------------------------------
214 : */
215 : void
216 69301 : ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
217 : {
218 : /* This should match ExecResetTupleTable's processing of one slot */
219 69301 : Assert(IsA(slot, TupleTableSlot));
220 69301 : ExecClearTuple(slot);
221 69301 : if (slot->tts_tupleDescriptor)
222 69268 : ReleaseTupleDesc(slot->tts_tupleDescriptor);
223 69301 : if (slot->tts_values)
224 69268 : pfree(slot->tts_values);
225 69301 : if (slot->tts_isnull)
226 69268 : pfree(slot->tts_isnull);
227 69301 : pfree(slot);
228 69301 : }
229 :
230 :
231 : /* ----------------------------------------------------------------
232 : * tuple table slot accessor functions
233 : * ----------------------------------------------------------------
234 : */
235 :
236 : /* --------------------------------
237 : * ExecSetSlotDescriptor
238 : *
239 : * This function is used to set the tuple descriptor associated
240 : * with the slot's tuple. The passed descriptor must have lifespan
241 : * at least equal to the slot's. If it is a reference-counted descriptor
242 : * then the reference count is incremented for as long as the slot holds
243 : * a reference.
244 : * --------------------------------
245 : */
246 : void
247 160473 : ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
248 : TupleDesc tupdesc) /* new tuple descriptor */
249 : {
250 : /* For safety, make sure slot is empty before changing it */
251 160473 : ExecClearTuple(slot);
252 :
253 : /*
254 : * Release any old descriptor. Also release old Datum/isnull arrays if
255 : * present (we don't bother to check if they could be re-used).
256 : */
257 160473 : if (slot->tts_tupleDescriptor)
258 38 : ReleaseTupleDesc(slot->tts_tupleDescriptor);
259 :
260 160473 : if (slot->tts_values)
261 38 : pfree(slot->tts_values);
262 160473 : if (slot->tts_isnull)
263 38 : pfree(slot->tts_isnull);
264 :
265 : /*
266 : * Install the new descriptor; if it's refcounted, bump its refcount.
267 : */
268 160473 : slot->tts_tupleDescriptor = tupdesc;
269 160473 : PinTupleDesc(tupdesc);
270 :
271 : /*
272 : * Allocate Datum/isnull arrays of the appropriate size. These must have
273 : * the same lifetime as the slot, so allocate in the slot's own context.
274 : */
275 160473 : slot->tts_values = (Datum *)
276 160473 : MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(Datum));
277 160473 : slot->tts_isnull = (bool *)
278 160473 : MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(bool));
279 160473 : }
280 :
281 : /* --------------------------------
282 : * ExecStoreTuple
283 : *
284 : * This function is used to store a physical tuple into a specified
285 : * slot in the tuple table.
286 : *
287 : * tuple: tuple to store
288 : * slot: slot to store it in
289 : * buffer: disk buffer if tuple is in a disk page, else InvalidBuffer
290 : * shouldFree: true if ExecClearTuple should pfree() the tuple
291 : * when done with it
292 : *
293 : * If 'buffer' is not InvalidBuffer, the tuple table code acquires a pin
294 : * on the buffer which is held until the slot is cleared, so that the tuple
295 : * won't go away on us.
296 : *
297 : * shouldFree is normally set 'true' for tuples constructed on-the-fly.
298 : * It must always be 'false' for tuples that are stored in disk pages,
299 : * since we don't want to try to pfree those.
300 : *
301 : * Another case where it is 'false' is when the referenced tuple is held
302 : * in a tuple table slot belonging to a lower-level executor Proc node.
303 : * In this case the lower-level slot retains ownership and responsibility
304 : * for eventually releasing the tuple. When this method is used, we must
305 : * be certain that the upper-level Proc node will lose interest in the tuple
306 : * sooner than the lower-level one does! If you're not certain, copy the
307 : * lower-level tuple with heap_copytuple and let the upper-level table
308 : * slot assume ownership of the copy!
309 : *
310 : * Return value is just the passed-in slot pointer.
311 : *
312 : * NOTE: before PostgreSQL 8.1, this function would accept a NULL tuple
313 : * pointer and effectively behave like ExecClearTuple (though you could
314 : * still specify a buffer to pin, which would be an odd combination).
315 : * This saved a couple lines of code in a few places, but seemed more likely
316 : * to mask logic errors than to be really useful, so it's now disallowed.
317 : * --------------------------------
318 : */
319 : TupleTableSlot *
320 4006212 : ExecStoreTuple(HeapTuple tuple,
321 : TupleTableSlot *slot,
322 : Buffer buffer,
323 : bool shouldFree)
324 : {
325 : /*
326 : * sanity checks
327 : */
328 4006212 : Assert(tuple != NULL);
329 4006212 : Assert(slot != NULL);
330 4006212 : Assert(slot->tts_tupleDescriptor != NULL);
331 : /* passing shouldFree=true for a tuple on a disk page is not sane */
332 4006212 : Assert(BufferIsValid(buffer) ? (!shouldFree) : true);
333 :
334 : /*
335 : * Free any old physical tuple belonging to the slot.
336 : */
337 4006212 : if (slot->tts_shouldFree)
338 97742 : heap_freetuple(slot->tts_tuple);
339 4006212 : if (slot->tts_shouldFreeMin)
340 501 : heap_free_minimal_tuple(slot->tts_mintuple);
341 :
342 : /*
343 : * Store the new tuple into the specified slot.
344 : */
345 4006212 : slot->tts_isempty = false;
346 4006212 : slot->tts_shouldFree = shouldFree;
347 4006212 : slot->tts_shouldFreeMin = false;
348 4006212 : slot->tts_tuple = tuple;
349 4006212 : slot->tts_mintuple = NULL;
350 :
351 : /* Mark extracted state invalid */
352 4006212 : slot->tts_nvalid = 0;
353 :
354 : /*
355 : * If tuple is on a disk page, keep the page pinned as long as we hold a
356 : * pointer into it. We assume the caller already has such a pin.
357 : *
358 : * This is coded to optimize the case where the slot previously held a
359 : * tuple on the same disk page: in that case releasing and re-acquiring
360 : * the pin is a waste of cycles. This is a common situation during
361 : * seqscans, so it's worth troubling over.
362 : */
363 4006212 : if (slot->tts_buffer != buffer)
364 : {
365 254889 : if (BufferIsValid(slot->tts_buffer))
366 128000 : ReleaseBuffer(slot->tts_buffer);
367 254889 : slot->tts_buffer = buffer;
368 254889 : if (BufferIsValid(buffer))
369 254878 : IncrBufferRefCount(buffer);
370 : }
371 :
372 4006212 : return slot;
373 : }
374 :
375 : /* --------------------------------
376 : * ExecStoreMinimalTuple
377 : *
378 : * Like ExecStoreTuple, but insert a "minimal" tuple into the slot.
379 : *
380 : * No 'buffer' parameter since minimal tuples are never stored in relations.
381 : * --------------------------------
382 : */
383 : TupleTableSlot *
384 9844354 : ExecStoreMinimalTuple(MinimalTuple mtup,
385 : TupleTableSlot *slot,
386 : bool shouldFree)
387 : {
388 : /*
389 : * sanity checks
390 : */
391 9844354 : Assert(mtup != NULL);
392 9844354 : Assert(slot != NULL);
393 9844354 : Assert(slot->tts_tupleDescriptor != NULL);
394 :
395 : /*
396 : * Free any old physical tuple belonging to the slot.
397 : */
398 9844354 : if (slot->tts_shouldFree)
399 7992 : heap_freetuple(slot->tts_tuple);
400 9844354 : if (slot->tts_shouldFreeMin)
401 282923 : heap_free_minimal_tuple(slot->tts_mintuple);
402 :
403 : /*
404 : * Drop the pin on the referenced buffer, if there is one.
405 : */
406 9844354 : if (BufferIsValid(slot->tts_buffer))
407 0 : ReleaseBuffer(slot->tts_buffer);
408 :
409 9844354 : slot->tts_buffer = InvalidBuffer;
410 :
411 : /*
412 : * Store the new tuple into the specified slot.
413 : */
414 9844354 : slot->tts_isempty = false;
415 9844354 : slot->tts_shouldFree = false;
416 9844354 : slot->tts_shouldFreeMin = shouldFree;
417 9844354 : slot->tts_tuple = &slot->tts_minhdr;
418 9844354 : slot->tts_mintuple = mtup;
419 :
420 9844354 : slot->tts_minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
421 9844354 : slot->tts_minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
422 : /* no need to set t_self or t_tableOid since we won't allow access */
423 :
424 : /* Mark extracted state invalid */
425 9844354 : slot->tts_nvalid = 0;
426 :
427 9844354 : return slot;
428 : }
429 :
430 : /* --------------------------------
431 : * ExecClearTuple
432 : *
433 : * This function is used to clear out a slot in the tuple table.
434 : *
435 : * NB: only the tuple is cleared, not the tuple descriptor (if any).
436 : * --------------------------------
437 : */
438 : TupleTableSlot * /* return: slot passed */
439 21552830 : ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
440 : {
441 : /*
442 : * sanity checks
443 : */
444 21552830 : Assert(slot != NULL);
445 :
446 : /*
447 : * Free the old physical tuple if necessary.
448 : */
449 21552830 : if (slot->tts_shouldFree)
450 532888 : heap_freetuple(slot->tts_tuple);
451 21552830 : if (slot->tts_shouldFreeMin)
452 307935 : heap_free_minimal_tuple(slot->tts_mintuple);
453 :
454 21552830 : slot->tts_tuple = NULL;
455 21552830 : slot->tts_mintuple = NULL;
456 21552830 : slot->tts_shouldFree = false;
457 21552830 : slot->tts_shouldFreeMin = false;
458 :
459 : /*
460 : * Drop the pin on the referenced buffer, if there is one.
461 : */
462 21552830 : if (BufferIsValid(slot->tts_buffer))
463 106222 : ReleaseBuffer(slot->tts_buffer);
464 :
465 21552830 : slot->tts_buffer = InvalidBuffer;
466 :
467 : /*
468 : * Mark it empty.
469 : */
470 21552830 : slot->tts_isempty = true;
471 21552830 : slot->tts_nvalid = 0;
472 :
473 21552830 : return slot;
474 : }
475 :
476 : /* --------------------------------
477 : * ExecStoreVirtualTuple
478 : * Mark a slot as containing a virtual tuple.
479 : *
480 : * The protocol for loading a slot with virtual tuple data is:
481 : * * Call ExecClearTuple to mark the slot empty.
482 : * * Store data into the Datum/isnull arrays.
483 : * * Call ExecStoreVirtualTuple to mark the slot valid.
484 : * This is a bit unclean but it avoids one round of data copying.
485 : * --------------------------------
486 : */
487 : TupleTableSlot *
488 768704 : ExecStoreVirtualTuple(TupleTableSlot *slot)
489 : {
490 : /*
491 : * sanity checks
492 : */
493 768704 : Assert(slot != NULL);
494 768704 : Assert(slot->tts_tupleDescriptor != NULL);
495 768704 : Assert(slot->tts_isempty);
496 :
497 768704 : slot->tts_isempty = false;
498 768704 : slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
499 :
500 768704 : return slot;
501 : }
502 :
503 : /* --------------------------------
504 : * ExecStoreAllNullTuple
505 : * Set up the slot to contain a null in every column.
506 : *
507 : * At first glance this might sound just like ExecClearTuple, but it's
508 : * entirely different: the slot ends up full, not empty.
509 : * --------------------------------
510 : */
511 : TupleTableSlot *
512 1082 : ExecStoreAllNullTuple(TupleTableSlot *slot)
513 : {
514 : /*
515 : * sanity checks
516 : */
517 1082 : Assert(slot != NULL);
518 1082 : Assert(slot->tts_tupleDescriptor != NULL);
519 :
520 : /* Clear any old contents */
521 1082 : ExecClearTuple(slot);
522 :
523 : /*
524 : * Fill all the columns of the virtual tuple with nulls
525 : */
526 1082 : MemSet(slot->tts_values, 0,
527 : slot->tts_tupleDescriptor->natts * sizeof(Datum));
528 1082 : memset(slot->tts_isnull, true,
529 1082 : slot->tts_tupleDescriptor->natts * sizeof(bool));
530 :
531 1082 : return ExecStoreVirtualTuple(slot);
532 : }
533 :
534 : /* --------------------------------
535 : * ExecCopySlotTuple
536 : * Obtain a copy of a slot's regular physical tuple. The copy is
537 : * palloc'd in the current memory context.
538 : * The slot itself is undisturbed.
539 : *
540 : * This works even if the slot contains a virtual or minimal tuple;
541 : * however the "system columns" of the result will not be meaningful.
542 : * --------------------------------
543 : */
544 : HeapTuple
545 667362 : ExecCopySlotTuple(TupleTableSlot *slot)
546 : {
547 : /*
548 : * sanity checks
549 : */
550 667362 : Assert(slot != NULL);
551 667362 : Assert(!slot->tts_isempty);
552 :
553 : /*
554 : * If we have a physical tuple (either format) then just copy it.
555 : */
556 667362 : if (TTS_HAS_PHYSICAL_TUPLE(slot))
557 23489 : return heap_copytuple(slot->tts_tuple);
558 643873 : if (slot->tts_mintuple)
559 62904 : return heap_tuple_from_minimal_tuple(slot->tts_mintuple);
560 :
561 : /*
562 : * Otherwise we need to build a tuple from the Datum array.
563 : */
564 580969 : return heap_form_tuple(slot->tts_tupleDescriptor,
565 : slot->tts_values,
566 : slot->tts_isnull);
567 : }
568 :
569 : /* --------------------------------
570 : * ExecCopySlotMinimalTuple
571 : * Obtain a copy of a slot's minimal physical tuple. The copy is
572 : * palloc'd in the current memory context.
573 : * The slot itself is undisturbed.
574 : * --------------------------------
575 : */
576 : MinimalTuple
577 749010 : ExecCopySlotMinimalTuple(TupleTableSlot *slot)
578 : {
579 : /*
580 : * sanity checks
581 : */
582 749010 : Assert(slot != NULL);
583 749010 : Assert(!slot->tts_isempty);
584 :
585 : /*
586 : * If we have a physical tuple then just copy it. Prefer to copy
587 : * tts_mintuple since that's a tad cheaper.
588 : */
589 749010 : if (slot->tts_mintuple)
590 47327 : return heap_copy_minimal_tuple(slot->tts_mintuple);
591 701683 : if (slot->tts_tuple)
592 36218 : return minimal_tuple_from_heap_tuple(slot->tts_tuple);
593 :
594 : /*
595 : * Otherwise we need to build a tuple from the Datum array.
596 : */
597 665465 : return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
598 : slot->tts_values,
599 : slot->tts_isnull);
600 : }
601 :
602 : /* --------------------------------
603 : * ExecFetchSlotTuple
604 : * Fetch the slot's regular physical tuple.
605 : *
606 : * If the slot contains a virtual tuple, we convert it to physical
607 : * form. The slot retains ownership of the physical tuple.
608 : * If it contains a minimal tuple we convert to regular form and store
609 : * that in addition to the minimal tuple (not instead of, because
610 : * callers may hold pointers to Datums within the minimal tuple).
611 : *
612 : * The main difference between this and ExecMaterializeSlot() is that this
613 : * does not guarantee that the contained tuple is local storage.
614 : * Hence, the result must be treated as read-only.
615 : * --------------------------------
616 : */
617 : HeapTuple
618 9831 : ExecFetchSlotTuple(TupleTableSlot *slot)
619 : {
620 : /*
621 : * sanity checks
622 : */
623 9831 : Assert(slot != NULL);
624 9831 : Assert(!slot->tts_isempty);
625 :
626 : /*
627 : * If we have a regular physical tuple then just return it.
628 : */
629 9831 : if (TTS_HAS_PHYSICAL_TUPLE(slot))
630 22 : return slot->tts_tuple;
631 :
632 : /*
633 : * Otherwise materialize the slot...
634 : */
635 9809 : return ExecMaterializeSlot(slot);
636 : }
637 :
638 : /* --------------------------------
639 : * ExecFetchSlotMinimalTuple
640 : * Fetch the slot's minimal physical tuple.
641 : *
642 : * If the slot contains a virtual tuple, we convert it to minimal
643 : * physical form. The slot retains ownership of the minimal tuple.
644 : * If it contains a regular tuple we convert to minimal form and store
645 : * that in addition to the regular tuple (not instead of, because
646 : * callers may hold pointers to Datums within the regular tuple).
647 : *
648 : * As above, the result must be treated as read-only.
649 : * --------------------------------
650 : */
651 : MinimalTuple
652 297167 : ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
653 : {
654 : MemoryContext oldContext;
655 :
656 : /*
657 : * sanity checks
658 : */
659 297167 : Assert(slot != NULL);
660 297167 : Assert(!slot->tts_isempty);
661 :
662 : /*
663 : * If we have a minimal physical tuple (local or not) then just return it.
664 : */
665 297167 : if (slot->tts_mintuple)
666 12343 : return slot->tts_mintuple;
667 :
668 : /*
669 : * Otherwise, copy or build a minimal tuple, and store it into the slot.
670 : *
671 : * We may be called in a context that is shorter-lived than the tuple
672 : * slot, but we have to ensure that the materialized tuple will survive
673 : * anyway.
674 : */
675 284824 : oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
676 284824 : slot->tts_mintuple = ExecCopySlotMinimalTuple(slot);
677 284824 : slot->tts_shouldFreeMin = true;
678 284824 : MemoryContextSwitchTo(oldContext);
679 :
680 : /*
681 : * Note: we may now have a situation where we have a local minimal tuple
682 : * attached to a virtual or non-local physical tuple. There seems no harm
683 : * in that at the moment, but if any materializes, we should change this
684 : * function to force the slot into minimal-tuple-only state.
685 : */
686 :
687 284824 : return slot->tts_mintuple;
688 : }
689 :
690 : /* --------------------------------
691 : * ExecFetchSlotTupleDatum
692 : * Fetch the slot's tuple as a composite-type Datum.
693 : *
694 : * The result is always freshly palloc'd in the caller's memory context.
695 : * --------------------------------
696 : */
697 : Datum
698 9809 : ExecFetchSlotTupleDatum(TupleTableSlot *slot)
699 : {
700 : HeapTuple tup;
701 : TupleDesc tupdesc;
702 :
703 : /* Fetch slot's contents in regular-physical-tuple form */
704 9809 : tup = ExecFetchSlotTuple(slot);
705 9809 : tupdesc = slot->tts_tupleDescriptor;
706 :
707 : /* Convert to Datum form */
708 9809 : return heap_copy_tuple_as_datum(tup, tupdesc);
709 : }
710 :
711 : /* --------------------------------
712 : * ExecMaterializeSlot
713 : * Force a slot into the "materialized" state.
714 : *
715 : * This causes the slot's tuple to be a local copy not dependent on
716 : * any external storage. A pointer to the contained tuple is returned.
717 : *
718 : * A typical use for this operation is to prepare a computed tuple
719 : * for being stored on disk. The original data may or may not be
720 : * virtual, but in any case we need a private copy for heap_insert
721 : * to scribble on.
722 : * --------------------------------
723 : */
724 : HeapTuple
725 559752 : ExecMaterializeSlot(TupleTableSlot *slot)
726 : {
727 : MemoryContext oldContext;
728 :
729 : /*
730 : * sanity checks
731 : */
732 559752 : Assert(slot != NULL);
733 559752 : Assert(!slot->tts_isempty);
734 :
735 : /*
736 : * If we have a regular physical tuple, and it's locally palloc'd, we have
737 : * nothing to do.
738 : */
739 559752 : if (slot->tts_tuple && slot->tts_shouldFree)
740 506 : return slot->tts_tuple;
741 :
742 : /*
743 : * Otherwise, copy or build a physical tuple, and store it into the slot.
744 : *
745 : * We may be called in a context that is shorter-lived than the tuple
746 : * slot, but we have to ensure that the materialized tuple will survive
747 : * anyway.
748 : */
749 559246 : oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
750 559246 : slot->tts_tuple = ExecCopySlotTuple(slot);
751 559246 : slot->tts_shouldFree = true;
752 559246 : MemoryContextSwitchTo(oldContext);
753 :
754 : /*
755 : * Drop the pin on the referenced buffer, if there is one.
756 : */
757 559246 : if (BufferIsValid(slot->tts_buffer))
758 20551 : ReleaseBuffer(slot->tts_buffer);
759 :
760 559246 : slot->tts_buffer = InvalidBuffer;
761 :
762 : /*
763 : * Mark extracted state invalid. This is important because the slot is
764 : * not supposed to depend any more on the previous external data; we
765 : * mustn't leave any dangling pass-by-reference datums in tts_values.
766 : * However, we have not actually invalidated any such datums, if there
767 : * happen to be any previously fetched from the slot. (Note in particular
768 : * that we have not pfree'd tts_mintuple, if there is one.)
769 : */
770 559246 : slot->tts_nvalid = 0;
771 :
772 : /*
773 : * On the same principle of not depending on previous remote storage,
774 : * forget the mintuple if it's not local storage. (If it is local
775 : * storage, we must not pfree it now, since callers might have already
776 : * fetched datum pointers referencing it.)
777 : */
778 559246 : if (!slot->tts_shouldFreeMin)
779 559246 : slot->tts_mintuple = NULL;
780 :
781 559246 : return slot->tts_tuple;
782 : }
783 :
784 : /* --------------------------------
785 : * ExecCopySlot
786 : * Copy the source slot's contents into the destination slot.
787 : *
788 : * The destination acquires a private copy that will not go away
789 : * if the source is cleared.
790 : *
791 : * The caller must ensure the slots have compatible tupdescs.
792 : * --------------------------------
793 : */
794 : TupleTableSlot *
795 57153 : ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
796 : {
797 : HeapTuple newTuple;
798 : MemoryContext oldContext;
799 :
800 : /*
801 : * There might be ways to optimize this when the source is virtual, but
802 : * for now just always build a physical copy. Make sure it is in the
803 : * right context.
804 : */
805 57153 : oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
806 57153 : newTuple = ExecCopySlotTuple(srcslot);
807 57153 : MemoryContextSwitchTo(oldContext);
808 :
809 57153 : return ExecStoreTuple(newTuple, dstslot, InvalidBuffer, true);
810 : }
811 :
812 :
813 : /* ----------------------------------------------------------------
814 : * convenience initialization routines
815 : * ----------------------------------------------------------------
816 : */
817 :
818 : /* --------------------------------
819 : * ExecInit{Result,Scan,Extra}TupleSlot
820 : *
821 : * These are convenience routines to initialize the specified slot
822 : * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
823 : * is used for initializing special-purpose slots.
824 : * --------------------------------
825 : */
826 :
827 : /* ----------------
828 : * ExecInitResultTupleSlot
829 : * ----------------
830 : */
831 : void
832 50679 : ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
833 : {
834 50679 : planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable);
835 50679 : }
836 :
837 : /* ----------------
838 : * ExecInitScanTupleSlot
839 : * ----------------
840 : */
841 : void
842 27584 : ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
843 : {
844 27584 : scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable);
845 27584 : }
846 :
847 : /* ----------------
848 : * ExecInitExtraTupleSlot
849 : * ----------------
850 : */
851 : TupleTableSlot *
852 16336 : ExecInitExtraTupleSlot(EState *estate)
853 : {
854 16336 : return ExecAllocTableSlot(&estate->es_tupleTable);
855 : }
856 :
857 : /* ----------------
858 : * ExecInitNullTupleSlot
859 : *
860 : * Build a slot containing an all-nulls tuple of the given type.
861 : * This is used as a substitute for an input tuple when performing an
862 : * outer join.
863 : * ----------------
864 : */
865 : TupleTableSlot *
866 1074 : ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
867 : {
868 1074 : TupleTableSlot *slot = ExecInitExtraTupleSlot(estate);
869 :
870 1074 : ExecSetSlotDescriptor(slot, tupType);
871 :
872 1074 : return ExecStoreAllNullTuple(slot);
873 : }
874 :
875 : /* ----------------------------------------------------------------
876 : * ExecTypeFromTL
877 : *
878 : * Generate a tuple descriptor for the result tuple of a targetlist.
879 : * (A parse/plan tlist must be passed, not an ExprState tlist.)
880 : * Note that resjunk columns, if any, are included in the result.
881 : *
882 : * Currently there are about 4 different places where we create
883 : * TupleDescriptors. They should all be merged, or perhaps
884 : * be rewritten to call BuildDesc().
885 : * ----------------------------------------------------------------
886 : */
887 : TupleDesc
888 54990 : ExecTypeFromTL(List *targetList, bool hasoid)
889 : {
890 54990 : return ExecTypeFromTLInternal(targetList, hasoid, false);
891 : }
892 :
893 : /* ----------------------------------------------------------------
894 : * ExecCleanTypeFromTL
895 : *
896 : * Same as above, but resjunk columns are omitted from the result.
897 : * ----------------------------------------------------------------
898 : */
899 : TupleDesc
900 7789 : ExecCleanTypeFromTL(List *targetList, bool hasoid)
901 : {
902 7789 : return ExecTypeFromTLInternal(targetList, hasoid, true);
903 : }
904 :
905 : static TupleDesc
906 62779 : ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
907 : {
908 : TupleDesc typeInfo;
909 : ListCell *l;
910 : int len;
911 62779 : int cur_resno = 1;
912 :
913 62779 : if (skipjunk)
914 7789 : len = ExecCleanTargetListLength(targetList);
915 : else
916 54990 : len = ExecTargetListLength(targetList);
917 62779 : typeInfo = CreateTemplateTupleDesc(len, hasoid);
918 :
919 203902 : foreach(l, targetList)
920 : {
921 141123 : TargetEntry *tle = lfirst(l);
922 :
923 141123 : if (skipjunk && tle->resjunk)
924 2410 : continue;
925 416139 : TupleDescInitEntry(typeInfo,
926 : cur_resno,
927 138713 : tle->resname,
928 138713 : exprType((Node *) tle->expr),
929 138713 : exprTypmod((Node *) tle->expr),
930 : 0);
931 138713 : TupleDescInitEntryCollation(typeInfo,
932 : cur_resno,
933 138713 : exprCollation((Node *) tle->expr));
934 138713 : cur_resno++;
935 : }
936 :
937 62779 : return typeInfo;
938 : }
939 :
940 : /*
941 : * ExecTypeFromExprList - build a tuple descriptor from a list of Exprs
942 : *
943 : * This is roughly like ExecTypeFromTL, but we work from bare expressions
944 : * not TargetEntrys. No names are attached to the tupledesc's columns.
945 : */
946 : TupleDesc
947 733 : ExecTypeFromExprList(List *exprList)
948 : {
949 : TupleDesc typeInfo;
950 : ListCell *lc;
951 733 : int cur_resno = 1;
952 :
953 733 : typeInfo = CreateTemplateTupleDesc(list_length(exprList), false);
954 :
955 1909 : foreach(lc, exprList)
956 : {
957 1176 : Node *e = lfirst(lc);
958 :
959 1176 : TupleDescInitEntry(typeInfo,
960 : cur_resno,
961 : NULL,
962 : exprType(e),
963 : exprTypmod(e),
964 : 0);
965 1176 : TupleDescInitEntryCollation(typeInfo,
966 : cur_resno,
967 : exprCollation(e));
968 1176 : cur_resno++;
969 : }
970 :
971 733 : return typeInfo;
972 : }
973 :
974 : /*
975 : * ExecTypeSetColNames - set column names in a TupleDesc
976 : *
977 : * Column names must be provided as an alias list (list of String nodes).
978 : *
979 : * For some callers, the supplied tupdesc has a named rowtype (not RECORD)
980 : * and it is moderately likely that the alias list matches the column names
981 : * already present in the tupdesc. If we do change any column names then
982 : * we must reset the tupdesc's type to anonymous RECORD; but we avoid doing
983 : * so if no names change.
984 : */
985 : void
986 556 : ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
987 : {
988 556 : bool modified = false;
989 556 : int colno = 0;
990 : ListCell *lc;
991 :
992 1418 : foreach(lc, namesList)
993 : {
994 862 : char *cname = strVal(lfirst(lc));
995 : Form_pg_attribute attr;
996 :
997 : /* Guard against too-long names list */
998 862 : if (colno >= typeInfo->natts)
999 0 : break;
1000 862 : attr = TupleDescAttr(typeInfo, colno);
1001 862 : colno++;
1002 :
1003 : /* Ignore empty aliases (these must be for dropped columns) */
1004 862 : if (cname[0] == '\0')
1005 18 : continue;
1006 :
1007 : /* Change tupdesc only if alias is actually different */
1008 844 : if (strcmp(cname, NameStr(attr->attname)) != 0)
1009 : {
1010 313 : namestrcpy(&(attr->attname), cname);
1011 313 : modified = true;
1012 : }
1013 : }
1014 :
1015 : /* If we modified the tupdesc, it's now a new record type */
1016 556 : if (modified)
1017 : {
1018 172 : typeInfo->tdtypeid = RECORDOID;
1019 172 : typeInfo->tdtypmod = -1;
1020 : }
1021 556 : }
1022 :
1023 : /*
1024 : * BlessTupleDesc - make a completed tuple descriptor useful for SRFs
1025 : *
1026 : * Rowtype Datums returned by a function must contain valid type information.
1027 : * This happens "for free" if the tupdesc came from a relcache entry, but
1028 : * not if we have manufactured a tupdesc for a transient RECORD datatype.
1029 : * In that case we have to notify typcache.c of the existence of the type.
1030 : */
1031 : TupleDesc
1032 3576 : BlessTupleDesc(TupleDesc tupdesc)
1033 : {
1034 6492 : if (tupdesc->tdtypeid == RECORDOID &&
1035 2916 : tupdesc->tdtypmod < 0)
1036 803 : assign_record_type_typmod(tupdesc);
1037 :
1038 3576 : return tupdesc; /* just for notational convenience */
1039 : }
1040 :
1041 : /*
1042 : * TupleDescGetSlot - Initialize a slot based on the supplied tupledesc
1043 : *
1044 : * Note: this is obsolete; it is sufficient to call BlessTupleDesc on
1045 : * the tupdesc. We keep it around just for backwards compatibility with
1046 : * existing user-written SRFs.
1047 : */
1048 : TupleTableSlot *
1049 0 : TupleDescGetSlot(TupleDesc tupdesc)
1050 : {
1051 : TupleTableSlot *slot;
1052 :
1053 : /* The useful work is here */
1054 0 : BlessTupleDesc(tupdesc);
1055 :
1056 : /* Make a standalone slot */
1057 0 : slot = MakeSingleTupleTableSlot(tupdesc);
1058 :
1059 : /* Return the slot */
1060 0 : return slot;
1061 : }
1062 :
1063 : /*
1064 : * TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the
1065 : * supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
1066 : * to produce a properly formed tuple.
1067 : */
1068 : AttInMetadata *
1069 32 : TupleDescGetAttInMetadata(TupleDesc tupdesc)
1070 : {
1071 32 : int natts = tupdesc->natts;
1072 : int i;
1073 : Oid atttypeid;
1074 : Oid attinfuncid;
1075 : FmgrInfo *attinfuncinfo;
1076 : Oid *attioparams;
1077 : int32 *atttypmods;
1078 : AttInMetadata *attinmeta;
1079 :
1080 32 : attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
1081 :
1082 : /* "Bless" the tupledesc so that we can make rowtype datums with it */
1083 32 : attinmeta->tupdesc = BlessTupleDesc(tupdesc);
1084 :
1085 : /*
1086 : * Gather info needed later to call the "in" function for each attribute
1087 : */
1088 32 : attinfuncinfo = (FmgrInfo *) palloc0(natts * sizeof(FmgrInfo));
1089 32 : attioparams = (Oid *) palloc0(natts * sizeof(Oid));
1090 32 : atttypmods = (int32 *) palloc0(natts * sizeof(int32));
1091 :
1092 135 : for (i = 0; i < natts; i++)
1093 : {
1094 103 : Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1095 :
1096 : /* Ignore dropped attributes */
1097 103 : if (!att->attisdropped)
1098 : {
1099 103 : atttypeid = att->atttypid;
1100 103 : getTypeInputInfo(atttypeid, &attinfuncid, &attioparams[i]);
1101 103 : fmgr_info(attinfuncid, &attinfuncinfo[i]);
1102 103 : atttypmods[i] = att->atttypmod;
1103 : }
1104 : }
1105 32 : attinmeta->attinfuncs = attinfuncinfo;
1106 32 : attinmeta->attioparams = attioparams;
1107 32 : attinmeta->atttypmods = atttypmods;
1108 :
1109 32 : return attinmeta;
1110 : }
1111 :
1112 : /*
1113 : * BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
1114 : * values is an array of C strings, one for each attribute of the return tuple.
1115 : * A NULL string pointer indicates we want to create a NULL field.
1116 : */
1117 : HeapTuple
1118 2107 : BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
1119 : {
1120 2107 : TupleDesc tupdesc = attinmeta->tupdesc;
1121 2107 : int natts = tupdesc->natts;
1122 : Datum *dvalues;
1123 : bool *nulls;
1124 : int i;
1125 : HeapTuple tuple;
1126 :
1127 2107 : dvalues = (Datum *) palloc(natts * sizeof(Datum));
1128 2107 : nulls = (bool *) palloc(natts * sizeof(bool));
1129 :
1130 : /* Call the "in" function for each non-dropped attribute */
1131 12006 : for (i = 0; i < natts; i++)
1132 : {
1133 9899 : if (!TupleDescAttr(tupdesc, i)->attisdropped)
1134 : {
1135 : /* Non-dropped attributes */
1136 39596 : dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i],
1137 9899 : values[i],
1138 9899 : attinmeta->attioparams[i],
1139 9899 : attinmeta->atttypmods[i]);
1140 9899 : if (values[i] != NULL)
1141 8403 : nulls[i] = false;
1142 : else
1143 1496 : nulls[i] = true;
1144 : }
1145 : else
1146 : {
1147 : /* Handle dropped attributes by setting to NULL */
1148 0 : dvalues[i] = (Datum) 0;
1149 0 : nulls[i] = true;
1150 : }
1151 : }
1152 :
1153 : /*
1154 : * Form a tuple
1155 : */
1156 2107 : tuple = heap_form_tuple(tupdesc, dvalues, nulls);
1157 :
1158 : /*
1159 : * Release locally palloc'd space. XXX would probably be good to pfree
1160 : * values of pass-by-reference datums, as well.
1161 : */
1162 2107 : pfree(dvalues);
1163 2107 : pfree(nulls);
1164 :
1165 2107 : return tuple;
1166 : }
1167 :
1168 : /*
1169 : * HeapTupleHeaderGetDatum - convert a HeapTupleHeader pointer to a Datum.
1170 : *
1171 : * This must *not* get applied to an on-disk tuple; the tuple should be
1172 : * freshly made by heap_form_tuple or some wrapper routine for it (such as
1173 : * BuildTupleFromCStrings). Be sure also that the tupledesc used to build
1174 : * the tuple has a properly "blessed" rowtype.
1175 : *
1176 : * Formerly this was a macro equivalent to PointerGetDatum, relying on the
1177 : * fact that heap_form_tuple fills in the appropriate tuple header fields
1178 : * for a composite Datum. However, we now require that composite Datums not
1179 : * contain any external TOAST pointers. We do not want heap_form_tuple itself
1180 : * to enforce that; more specifically, the rule applies only to actual Datums
1181 : * and not to HeapTuple structures. Therefore, HeapTupleHeaderGetDatum is
1182 : * now a function that detects whether there are externally-toasted fields
1183 : * and constructs a new tuple with inlined fields if so. We still need
1184 : * heap_form_tuple to insert the Datum header fields, because otherwise this
1185 : * code would have no way to obtain a tupledesc for the tuple.
1186 : *
1187 : * Note that if we do build a new tuple, it's palloc'd in the current
1188 : * memory context. Beware of code that changes context between the initial
1189 : * heap_form_tuple/etc call and calling HeapTuple(Header)GetDatum.
1190 : *
1191 : * For performance-critical callers, it could be worthwhile to take extra
1192 : * steps to ensure that there aren't TOAST pointers in the output of
1193 : * heap_form_tuple to begin with. It's likely however that the costs of the
1194 : * typcache lookup and tuple disassembly/reassembly are swamped by TOAST
1195 : * dereference costs, so that the benefits of such extra effort would be
1196 : * minimal.
1197 : *
1198 : * XXX it would likely be better to create wrapper functions that produce
1199 : * a composite Datum from the field values in one step. However, there's
1200 : * enough code using the existing APIs that we couldn't get rid of this
1201 : * hack anytime soon.
1202 : */
1203 : Datum
1204 6109 : HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
1205 : {
1206 : Datum result;
1207 : TupleDesc tupDesc;
1208 :
1209 : /* No work if there are no external TOAST pointers in the tuple */
1210 6109 : if (!HeapTupleHeaderHasExternal(tuple))
1211 6107 : return PointerGetDatum(tuple);
1212 :
1213 : /* Use the type data saved by heap_form_tuple to look up the rowtype */
1214 2 : tupDesc = lookup_rowtype_tupdesc(HeapTupleHeaderGetTypeId(tuple),
1215 : HeapTupleHeaderGetTypMod(tuple));
1216 :
1217 : /* And do the flattening */
1218 2 : result = toast_flatten_tuple_to_datum(tuple,
1219 2 : HeapTupleHeaderGetDatumLength(tuple),
1220 : tupDesc);
1221 :
1222 2 : ReleaseTupleDesc(tupDesc);
1223 :
1224 2 : return result;
1225 : }
1226 :
1227 :
1228 : /*
1229 : * Functions for sending tuples to the frontend (or other specified destination)
1230 : * as though it is a SELECT result. These are used by utility commands that
1231 : * need to project directly to the destination and don't need or want full
1232 : * table function capability. Currently used by EXPLAIN and SHOW ALL.
1233 : */
1234 : TupOutputState *
1235 1180 : begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
1236 : {
1237 : TupOutputState *tstate;
1238 :
1239 1180 : tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
1240 :
1241 1180 : tstate->slot = MakeSingleTupleTableSlot(tupdesc);
1242 1180 : tstate->dest = dest;
1243 :
1244 1180 : (*tstate->dest->rStartup) (tstate->dest, (int) CMD_SELECT, tupdesc);
1245 :
1246 1180 : return tstate;
1247 : }
1248 :
1249 : /*
1250 : * write a single tuple
1251 : */
1252 : void
1253 5943 : do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
1254 : {
1255 5943 : TupleTableSlot *slot = tstate->slot;
1256 5943 : int natts = slot->tts_tupleDescriptor->natts;
1257 :
1258 : /* make sure the slot is clear */
1259 5943 : ExecClearTuple(slot);
1260 :
1261 : /* insert data */
1262 5943 : memcpy(slot->tts_values, values, natts * sizeof(Datum));
1263 5943 : memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
1264 :
1265 : /* mark slot as containing a virtual tuple */
1266 5943 : ExecStoreVirtualTuple(slot);
1267 :
1268 : /* send the tuple to the receiver */
1269 5943 : (void) (*tstate->dest->receiveSlot) (slot, tstate->dest);
1270 :
1271 : /* clean up */
1272 5943 : ExecClearTuple(slot);
1273 5943 : }
1274 :
1275 : /*
1276 : * write a chunk of text, breaking at newline characters
1277 : *
1278 : * Should only be used with a single-TEXT-attribute tupdesc.
1279 : */
1280 : void
1281 1115 : do_text_output_multiline(TupOutputState *tstate, const char *txt)
1282 : {
1283 : Datum values[1];
1284 1115 : bool isnull[1] = {false};
1285 :
1286 8108 : while (*txt)
1287 : {
1288 : const char *eol;
1289 : int len;
1290 :
1291 5878 : eol = strchr(txt, '\n');
1292 5878 : if (eol)
1293 : {
1294 5878 : len = eol - txt;
1295 5878 : eol++;
1296 : }
1297 : else
1298 : {
1299 0 : len = strlen(txt);
1300 0 : eol = txt + len;
1301 : }
1302 :
1303 5878 : values[0] = PointerGetDatum(cstring_to_text_with_len(txt, len));
1304 5878 : do_tup_output(tstate, values, isnull);
1305 5878 : pfree(DatumGetPointer(values[0]));
1306 5878 : txt = eol;
1307 : }
1308 1115 : }
1309 :
1310 : void
1311 1180 : end_tup_output(TupOutputState *tstate)
1312 : {
1313 1180 : (*tstate->dest->rShutdown) (tstate->dest);
1314 : /* note that destroying the dest is not ours to do */
1315 1180 : ExecDropSingleTupleTableSlot(tstate->slot);
1316 1180 : pfree(tstate);
1317 1180 : }
|