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