]> granicus.if.org Git - postgresql/blob - src/backend/executor/execTuples.c
Make some small planner API cleanups.
[postgresql] / src / backend / executor / execTuples.c
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  *
16  *       EXAMPLE OF HOW TABLE ROUTINES WORK
17  *              Suppose we have a query such as SELECT emp.name FROM emp and we have
18  *              a single SeqScan node in the query plan.
19  *
20  *              At ExecutorStart()
21  *              ----------------
22
23  *              - ExecInitSeqScan() calls ExecInitScanTupleSlot() to construct a
24  *                TupleTableSlots for the tuples returned by the access method, and
25  *                ExecInitResultTypeTL() to define the node's return
26  *                type. ExecAssignScanProjectionInfo() will, if necessary, create
27  *                another TupleTableSlot for the tuples resulting from performing
28  *                target list projections.
29  *
30  *              During ExecutorRun()
31  *              ----------------
32  *              - SeqNext() calls ExecStoreBufferHeapTuple() to place the tuple
33  *                returned by the access method into the scan tuple slot.
34  *
35  *              - ExecSeqScan() (via ExecScan), if necessary, calls ExecProject(),
36  *                putting the result of the projection in the result tuple slot. If
37  *                not necessary, it directly returns the slot returned by SeqNext().
38  *
39  *              - ExecutePlan() calls the output function.
40  *
41  *              The important thing to watch in the executor code is how pointers
42  *              to the slots containing tuples are passed instead of the tuples
43  *              themselves.  This facilitates the communication of related information
44  *              (such as whether or not a tuple should be pfreed, what buffer contains
45  *              this tuple, the tuple's tuple descriptor, etc).  It also allows us
46  *              to avoid physically constructing projection tuples in many cases.
47  *
48  *
49  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
50  * Portions Copyright (c) 1994, Regents of the University of California
51  *
52  *
53  * IDENTIFICATION
54  *        src/backend/executor/execTuples.c
55  *
56  *-------------------------------------------------------------------------
57  */
58 #include "postgres.h"
59
60 #include "access/htup_details.h"
61 #include "access/tupdesc_details.h"
62 #include "access/tuptoaster.h"
63 #include "funcapi.h"
64 #include "catalog/pg_type.h"
65 #include "nodes/nodeFuncs.h"
66 #include "storage/bufmgr.h"
67 #include "utils/builtins.h"
68 #include "utils/lsyscache.h"
69 #include "utils/typcache.h"
70
71
72 static TupleDesc ExecTypeFromTLInternal(List *targetList,
73                                            bool skipjunk);
74 static pg_attribute_always_inline void
75 slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
76                                            int natts);
77 static void tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer);
78
79
80 const TupleTableSlotOps TTSOpsVirtual;
81 const TupleTableSlotOps TTSOpsHeapTuple;
82 const TupleTableSlotOps TTSOpsMinimalTuple;
83 const TupleTableSlotOps TTSOpsBufferHeapTuple;
84
85
86 /*
87  * TupleTableSlotOps implementations.
88  */
89
90 /*
91  * TupleTableSlotOps implementation for VirtualTupleTableSlot.
92  */
93 static void
94 tts_virtual_init(TupleTableSlot *slot)
95 {
96 }
97
98 static void
99 tts_virtual_release(TupleTableSlot *slot)
100 {
101 }
102
103 static void
104 tts_virtual_clear(TupleTableSlot *slot)
105 {
106         if (unlikely(TTS_SHOULDFREE(slot)))
107         {
108                 VirtualTupleTableSlot *vslot = (VirtualTupleTableSlot *) slot;
109
110                 pfree(vslot->data);
111                 vslot->data = NULL;
112
113                 slot->tts_flags = ~TTS_FLAG_SHOULDFREE;
114         }
115
116         slot->tts_nvalid = 0;
117         slot->tts_flags |= TTS_FLAG_EMPTY;
118 }
119
120 /*
121  * Attribute values are readily available in tts_values and tts_isnull array
122  * in a VirtualTupleTableSlot. So there should be no need to call either of the
123  * following two functions.
124  */
125 static void
126 tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
127 {
128         elog(ERROR, "getsomeattrs is not required to be called on a virtual tuple table slot");
129 }
130
131 static Datum
132 tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
133 {
134         elog(ERROR, "virtual tuple table slot does not have system atttributes");
135
136         return 0; /* silence compiler warnings */
137 }
138
139 /*
140  * To materialize a virtual slot all the datums that aren't passed by value
141  * have to be copied into the slot's memory context.  To do so, compute the
142  * required size, and allocate enough memory to store all attributes.  That's
143  * good for cache hit ratio, but more importantly requires only memory
144  * allocation/deallocation.
145  */
146 static void
147 tts_virtual_materialize(TupleTableSlot *slot)
148 {
149         VirtualTupleTableSlot *vslot = (VirtualTupleTableSlot *) slot;
150         TupleDesc       desc = slot->tts_tupleDescriptor;
151         Size            sz = 0;
152         char       *data;
153
154         /* already materialized */
155         if (TTS_SHOULDFREE(slot))
156                 return;
157
158         /* compute size of memory required */
159         for (int natt = 0; natt < desc->natts; natt++)
160         {
161                 Form_pg_attribute att = TupleDescAttr(desc, natt);
162                 Datum val;
163
164                 if (att->attbyval || slot->tts_isnull[natt])
165                         continue;
166
167                 val = slot->tts_values[natt];
168
169                 if (att->attlen == -1 &&
170                         VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
171                 {
172                         /*
173                          * We want to flatten the expanded value so that the materialized
174                          * slot doesn't depend on it.
175                          */
176                         sz = att_align_nominal(sz, att->attalign);
177                         sz += EOH_get_flat_size(DatumGetEOHP(val));
178                 }
179                 else
180                 {
181                         sz = att_align_nominal(sz, att->attalign);
182                         sz = att_addlength_datum(sz, att->attlen, val);
183                 }
184         }
185
186         /* all data is byval */
187         if (sz == 0)
188                 return;
189
190         /* allocate memory */
191         vslot->data = data = MemoryContextAlloc(slot->tts_mcxt, sz);
192         slot->tts_flags |= TTS_FLAG_SHOULDFREE;
193
194         /* and copy all attributes into the pre-allocated space */
195         for (int natt = 0; natt < desc->natts; natt++)
196         {
197                 Form_pg_attribute att = TupleDescAttr(desc, natt);
198                 Datum val;
199
200                 if (att->attbyval || slot->tts_isnull[natt])
201                         continue;
202
203                 val = slot->tts_values[natt];
204
205                 if (att->attlen == -1 &&
206                         VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
207                 {
208                         Size data_length;
209
210                         /*
211                          * We want to flatten the expanded value so that the materialized
212                          * slot doesn't depend on it.
213                          */
214                         ExpandedObjectHeader *eoh = DatumGetEOHP(val);
215
216                         data = (char *) att_align_nominal(data,
217                                                                                           att->attalign);
218                         data_length = EOH_get_flat_size(eoh);
219                         EOH_flatten_into(eoh, data, data_length);
220
221                         slot->tts_values[natt] = PointerGetDatum(data);
222                         data += data_length;
223                 }
224                 else
225                 {
226                         Size data_length = 0;
227
228                         data = (char *) att_align_nominal(data, att->attalign);
229                         data_length = att_addlength_datum(data_length, att->attlen, val);
230
231                         memcpy(data, DatumGetPointer(val), data_length);
232
233                         slot->tts_values[natt] = PointerGetDatum(data);
234                         data += data_length;
235                 }
236         }
237 }
238
239 static void
240 tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
241 {
242         TupleDesc       srcdesc = dstslot->tts_tupleDescriptor;
243
244         Assert(srcdesc->natts <= dstslot->tts_tupleDescriptor->natts);
245
246         tts_virtual_clear(dstslot);
247
248         slot_getallattrs(srcslot);
249
250         for (int natt = 0; natt < srcdesc->natts; natt++)
251         {
252                 dstslot->tts_values[natt] = srcslot->tts_values[natt];
253                 dstslot->tts_isnull[natt] = srcslot->tts_isnull[natt];
254         }
255
256         dstslot->tts_nvalid = srcdesc->natts;
257         dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
258
259         /* make sure storage doesn't depend on external memory */
260         tts_virtual_materialize(dstslot);
261 }
262
263 static HeapTuple
264 tts_virtual_copy_heap_tuple(TupleTableSlot *slot)
265 {
266         Assert(!TTS_EMPTY(slot));
267
268         return heap_form_tuple(slot->tts_tupleDescriptor,
269                                                    slot->tts_values,
270                                                    slot->tts_isnull);
271
272 }
273
274 static MinimalTuple
275 tts_virtual_copy_minimal_tuple(TupleTableSlot *slot)
276 {
277         Assert(!TTS_EMPTY(slot));
278
279         return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
280                                                                    slot->tts_values,
281                                                                    slot->tts_isnull);
282 }
283
284
285 /*
286  * TupleTableSlotOps implementation for HeapTupleTableSlot.
287  */
288
289 static void
290 tts_heap_init(TupleTableSlot *slot)
291 {
292 }
293
294 static void
295 tts_heap_release(TupleTableSlot *slot)
296 {
297 }
298
299 static void
300 tts_heap_clear(TupleTableSlot *slot)
301 {
302         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
303
304         /* Free the memory for the heap tuple if it's allowed. */
305         if (TTS_SHOULDFREE(slot))
306         {
307                 heap_freetuple(hslot->tuple);
308                 slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
309         }
310
311         slot->tts_nvalid = 0;
312         slot->tts_flags |= TTS_FLAG_EMPTY;
313         hslot->off = 0;
314         hslot->tuple = NULL;
315 }
316
317 static void
318 tts_heap_getsomeattrs(TupleTableSlot *slot, int natts)
319 {
320         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
321
322         Assert(!TTS_EMPTY(slot));
323
324         slot_deform_heap_tuple(slot, hslot->tuple, &hslot->off, natts);
325 }
326
327 static Datum
328 tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
329 {
330         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
331
332         return heap_getsysattr(hslot->tuple, attnum,
333                                                    slot->tts_tupleDescriptor, isnull);
334 }
335
336 static void
337 tts_heap_materialize(TupleTableSlot *slot)
338 {
339         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
340         MemoryContext oldContext;
341
342         Assert(!TTS_EMPTY(slot));
343
344         /* This slot has it's tuple already materialized. Nothing to do. */
345         if (TTS_SHOULDFREE(slot))
346                 return;
347
348         slot->tts_flags |= TTS_FLAG_SHOULDFREE;
349
350         oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
351
352         if (!hslot->tuple)
353                 hslot->tuple = heap_form_tuple(slot->tts_tupleDescriptor,
354                                                                            slot->tts_values,
355                                                                            slot->tts_isnull);
356         else
357         {
358                 /*
359                  * The tuple contained in this slot is not allocated in the memory
360                  * context of the given slot (else it would have TTS_SHOULDFREE set).
361                  * Copy the tuple into the given slot's memory context.
362                  */
363                 hslot->tuple = heap_copytuple(hslot->tuple);
364         }
365
366         /*
367          * Have to deform from scratch, otherwise tts_values[] entries could point
368          * into the non-materialized tuple (which might be gone when accessed).
369          */
370         slot->tts_nvalid = 0;
371         hslot->off = 0;
372
373         MemoryContextSwitchTo(oldContext);
374 }
375
376 static void
377 tts_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
378 {
379         HeapTuple tuple;
380         MemoryContext oldcontext;
381
382         oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
383         tuple = ExecCopySlotHeapTuple(srcslot);
384         MemoryContextSwitchTo(oldcontext);
385
386         ExecStoreHeapTuple(tuple, dstslot, true);
387 }
388
389 static HeapTuple
390 tts_heap_get_heap_tuple(TupleTableSlot *slot)
391 {
392         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
393
394         Assert(!TTS_EMPTY(slot));
395         if (!hslot->tuple)
396                 tts_heap_materialize(slot);
397
398         return hslot->tuple;
399 }
400
401 static HeapTuple
402 tts_heap_copy_heap_tuple(TupleTableSlot *slot)
403 {
404         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
405
406         Assert(!TTS_EMPTY(slot));
407         if (!hslot->tuple)
408                 tts_heap_materialize(slot);
409
410         return heap_copytuple(hslot->tuple);
411 }
412
413 static MinimalTuple
414 tts_heap_copy_minimal_tuple(TupleTableSlot *slot)
415 {
416         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
417
418         if (!hslot->tuple)
419                 tts_heap_materialize(slot);
420
421         return minimal_tuple_from_heap_tuple(hslot->tuple);
422 }
423
424 static void
425 tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
426 {
427         HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
428
429         tts_heap_clear(slot);
430
431         slot->tts_nvalid = 0;
432         hslot->tuple = tuple;
433         hslot->off = 0;
434         slot->tts_flags &= ~TTS_FLAG_EMPTY;
435
436         if (shouldFree)
437                 slot->tts_flags |= TTS_FLAG_SHOULDFREE;
438 }
439
440
441 /*
442  * TupleTableSlotOps implementation for MinimalTupleTableSlot.
443  */
444
445 static void
446 tts_minimal_init(TupleTableSlot *slot)
447 {
448         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
449
450         /*
451          * Initialize the heap tuple pointer to access attributes of the minimal
452          * tuple contained in the slot as if its a heap tuple.
453          */
454         mslot->tuple = &mslot->minhdr;
455 }
456
457 static void
458 tts_minimal_release(TupleTableSlot *slot)
459 {
460 }
461
462 static void
463 tts_minimal_clear(TupleTableSlot *slot)
464 {
465         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
466
467         if (TTS_SHOULDFREE(slot))
468         {
469                 heap_free_minimal_tuple(mslot->mintuple);
470                 slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
471         }
472
473         slot->tts_nvalid = 0;
474         slot->tts_flags |= TTS_FLAG_EMPTY;
475         mslot->off = 0;
476         mslot->mintuple = NULL;
477 }
478
479 static void
480 tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
481 {
482         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
483
484         Assert(!TTS_EMPTY(slot));
485
486         slot_deform_heap_tuple(slot, mslot->tuple, &mslot->off, natts);
487 }
488
489 static Datum
490 tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
491 {
492         elog(ERROR, "minimal tuple table slot does not have system atttributes");
493
494         return 0; /* silence compiler warnings */
495 }
496
497 static void
498 tts_minimal_materialize(TupleTableSlot *slot)
499 {
500         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
501         MemoryContext oldContext;
502
503         Assert(!TTS_EMPTY(slot));
504
505         /* This slot has it's tuple already materialized. Nothing to do. */
506         if (TTS_SHOULDFREE(slot))
507                 return;
508
509         slot->tts_flags |= TTS_FLAG_SHOULDFREE;
510         oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
511
512         if (!mslot->mintuple)
513         {
514                 mslot->mintuple = heap_form_minimal_tuple(slot->tts_tupleDescriptor,
515                                                                                                   slot->tts_values,
516                                                                                                   slot->tts_isnull);
517         }
518         else
519         {
520                 /*
521                  * The minimal tuple contained in this slot is not allocated in the
522                  * memory context of the given slot (else it would have TTS_SHOULDFREE
523                  * set).  Copy the minimal tuple into the given slot's memory context.
524                  */
525                 mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple);
526         }
527
528         Assert(mslot->tuple == &mslot->minhdr);
529
530         mslot->minhdr.t_len = mslot->mintuple->t_len + MINIMAL_TUPLE_OFFSET;
531         mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mslot->mintuple - MINIMAL_TUPLE_OFFSET);
532
533         MemoryContextSwitchTo(oldContext);
534
535         /*
536          * Have to deform from scratch, otherwise tts_values[] entries could point
537          * into the non-materialized tuple (which might be gone when accessed).
538          */
539         slot->tts_nvalid = 0;
540         mslot->off = 0;
541 }
542
543 static void
544 tts_minimal_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
545 {
546         MemoryContext oldcontext;
547         MinimalTuple mintuple;
548
549         oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
550         mintuple = ExecCopySlotMinimalTuple(srcslot);
551         MemoryContextSwitchTo(oldcontext);
552
553         ExecStoreMinimalTuple(mintuple, dstslot, true);
554 }
555
556 static MinimalTuple
557 tts_minimal_get_minimal_tuple(TupleTableSlot *slot)
558 {
559         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
560
561         if (!mslot->mintuple)
562                 tts_minimal_materialize(slot);
563
564         return mslot->mintuple;
565 }
566
567 static HeapTuple
568 tts_minimal_copy_heap_tuple(TupleTableSlot *slot)
569 {
570         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
571
572         if (!mslot->mintuple)
573                 tts_minimal_materialize(slot);
574
575         return heap_tuple_from_minimal_tuple(mslot->mintuple);
576 }
577
578 static MinimalTuple
579 tts_minimal_copy_minimal_tuple(TupleTableSlot *slot)
580 {
581         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
582
583         if (!mslot->mintuple)
584                 tts_minimal_materialize(slot);
585
586         return heap_copy_minimal_tuple(mslot->mintuple);
587 }
588
589 static void
590 tts_minimal_store_tuple(TupleTableSlot *slot, MinimalTuple mtup, bool shouldFree)
591 {
592         MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
593
594         tts_minimal_clear(slot);
595
596         Assert(!TTS_SHOULDFREE(slot));
597         Assert(TTS_EMPTY(slot));
598
599         slot->tts_flags &= ~TTS_FLAG_EMPTY;
600         slot->tts_nvalid = 0;
601         mslot->off = 0;
602
603         mslot->mintuple = mtup;
604         Assert(mslot->tuple == &mslot->minhdr);
605         mslot->minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
606         mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
607         /* no need to set t_self or t_tableOid since we won't allow access */
608
609         if (shouldFree)
610                 slot->tts_flags |= TTS_FLAG_SHOULDFREE;
611         else
612                 Assert(!TTS_SHOULDFREE(slot));
613 }
614
615
616 /*
617  * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
618  */
619
620 static void
621 tts_buffer_heap_init(TupleTableSlot *slot)
622 {
623 }
624
625 static void
626 tts_buffer_heap_release(TupleTableSlot *slot)
627 {
628 }
629
630 static void
631 tts_buffer_heap_clear(TupleTableSlot *slot)
632 {
633         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
634
635         /*
636          * Free the memory for heap tuple if allowed. A tuple coming from buffer
637          * can never be freed. But we may have materialized a tuple from buffer.
638          * Such a tuple can be freed.
639          */
640         if (TTS_SHOULDFREE(slot))
641         {
642                 /* We should have unpinned the buffer while materializing the tuple. */
643                 Assert(!BufferIsValid(bslot->buffer));
644
645                 heap_freetuple(bslot->base.tuple);
646                 slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
647
648                 Assert(!BufferIsValid(bslot->buffer));
649         }
650
651         if (BufferIsValid(bslot->buffer))
652                 ReleaseBuffer(bslot->buffer);
653
654         slot->tts_nvalid = 0;
655         slot->tts_flags |= TTS_FLAG_EMPTY;
656         bslot->base.tuple = NULL;
657         bslot->base.off = 0;
658         bslot->buffer = InvalidBuffer;
659 }
660
661 static void
662 tts_buffer_heap_getsomeattrs(TupleTableSlot *slot, int natts)
663 {
664         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
665
666         Assert(!TTS_EMPTY(slot));
667
668         slot_deform_heap_tuple(slot, bslot->base.tuple, &bslot->base.off, natts);
669 }
670
671 static Datum
672 tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
673 {
674         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
675
676         return heap_getsysattr(bslot->base.tuple, attnum,
677                                                    slot->tts_tupleDescriptor, isnull);
678 }
679
680 static void
681 tts_buffer_heap_materialize(TupleTableSlot *slot)
682 {
683         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
684         MemoryContext oldContext;
685
686         Assert(!TTS_EMPTY(slot));
687
688         /* If already materialized nothing to do. */
689         if (TTS_SHOULDFREE(slot))
690                 return;
691
692         slot->tts_flags |= TTS_FLAG_SHOULDFREE;
693
694         /*
695          * A heap tuple stored in a BufferHeapTupleTableSlot should have a buffer
696          * associated with it, unless it's materialized (which would've returned
697          * above).
698          */
699         Assert(bslot->base.tuple);
700
701         oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
702         bslot->base.tuple = heap_copytuple(bslot->base.tuple);
703         MemoryContextSwitchTo(oldContext);
704
705         /*
706          * A heap tuple stored in a BufferHeapTupleTableSlot should have a buffer
707          * associated with it, unless it's materialized.
708          */
709         Assert(BufferIsValid(bslot->buffer));
710         if (likely(BufferIsValid(bslot->buffer)))
711                 ReleaseBuffer(bslot->buffer);
712         bslot->buffer = InvalidBuffer;
713
714         /*
715          * Have to deform from scratch, otherwise tts_values[] entries could point
716          * into the non-materialized tuple (which might be gone when accessed).
717          */
718         bslot->base.off = 0;
719         slot->tts_nvalid = 0;
720 }
721
722 static void
723 tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
724 {
725         BufferHeapTupleTableSlot *bsrcslot = (BufferHeapTupleTableSlot *) srcslot;
726         BufferHeapTupleTableSlot *bdstslot = (BufferHeapTupleTableSlot *) dstslot;
727
728         /*
729          * If the source slot is of a different kind, or is a buffer slot that has
730          * been materialized, make a new copy of the tuple.
731          */
732         if (dstslot->tts_ops != srcslot->tts_ops ||
733                 TTS_SHOULDFREE(srcslot))
734         {
735                 MemoryContext oldContext;
736
737                 ExecClearTuple(dstslot);
738                 dstslot->tts_flags |= TTS_FLAG_SHOULDFREE;
739                 dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
740                 oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
741                 bdstslot->base.tuple = ExecCopySlotHeapTuple(srcslot);
742                 MemoryContextSwitchTo(oldContext);
743         }
744         else
745         {
746                 tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple, bsrcslot->buffer);
747                 /*
748                  * Need to materialize because the HeapTupleData portion of the tuple
749                  * might be in a foreign memory context. That's annoying, but until
750                  * that's moved into the slot, unavoidable.
751                  */
752                 tts_buffer_heap_materialize(dstslot);
753         }
754 }
755
756 static HeapTuple
757 tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
758 {
759         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
760
761         Assert(!TTS_EMPTY(slot));
762
763         if (!bslot->base.tuple)
764                 tts_buffer_heap_materialize(slot);
765
766         return bslot->base.tuple;
767 }
768
769 static HeapTuple
770 tts_buffer_heap_copy_heap_tuple(TupleTableSlot *slot)
771 {
772         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
773
774         Assert(!TTS_EMPTY(slot));
775
776         if (!bslot->base.tuple)
777                 tts_buffer_heap_materialize(slot);
778
779         return heap_copytuple(bslot->base.tuple);
780 }
781
782 static MinimalTuple
783 tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot)
784 {
785         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
786
787         Assert(!TTS_EMPTY(slot));
788
789         if (!bslot->base.tuple)
790                 tts_buffer_heap_materialize(slot);
791
792         return minimal_tuple_from_heap_tuple(bslot->base.tuple);
793 }
794
795 static void
796 tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
797 {
798         BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
799
800         if (TTS_SHOULDFREE(slot))
801         {
802                 /* materialized slot shouldn't have a buffer to release */
803                 Assert(!BufferIsValid(bslot->buffer));
804
805                 heap_freetuple(bslot->base.tuple);
806                 slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
807         }
808
809         slot->tts_flags &= ~TTS_FLAG_EMPTY;
810         slot->tts_nvalid = 0;
811         bslot->base.tuple = tuple;
812         bslot->base.off = 0;
813
814         /*
815          * If tuple is on a disk page, keep the page pinned as long as we hold a
816          * pointer into it.  We assume the caller already has such a pin.
817          *
818          * This is coded to optimize the case where the slot previously held a
819          * tuple on the same disk page: in that case releasing and re-acquiring
820          * the pin is a waste of cycles.  This is a common situation during
821          * seqscans, so it's worth troubling over.
822          */
823         if (bslot->buffer != buffer)
824         {
825                 if (BufferIsValid(bslot->buffer))
826                         ReleaseBuffer(bslot->buffer);
827                 bslot->buffer = buffer;
828                 IncrBufferRefCount(buffer);
829         }
830 }
831
832 /*
833  * slot_deform_heap_tuple
834  *              Given a TupleTableSlot, extract data from the slot's physical tuple
835  *              into its Datum/isnull arrays.  Data is extracted up through the
836  *              natts'th column (caller must ensure this is a legal column number).
837  *
838  *              This is essentially an incremental version of heap_deform_tuple:
839  *              on each call we extract attributes up to the one needed, without
840  *              re-computing information about previously extracted attributes.
841  *              slot->tts_nvalid is the number of attributes already extracted.
842  *
843  * This is marked as always inline, so the different offp for different types
844  * of slots gets optimized away.
845  */
846 static pg_attribute_always_inline void
847 slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
848                                            int natts)
849 {
850         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
851         Datum      *values = slot->tts_values;
852         bool       *isnull = slot->tts_isnull;
853         HeapTupleHeader tup = tuple->t_data;
854         bool            hasnulls = HeapTupleHasNulls(tuple);
855         int                     attnum;
856         char       *tp;                         /* ptr to tuple data */
857         uint32          off;                    /* offset in tuple data */
858         bits8      *bp = tup->t_bits;   /* ptr to null bitmap in tuple */
859         bool            slow;                   /* can we use/set attcacheoff? */
860
861         /* We can only fetch as many attributes as the tuple has. */
862         natts = Min(HeapTupleHeaderGetNatts(tuple->t_data), natts);
863
864         /*
865          * Check whether the first call for this tuple, and initialize or restore
866          * loop state.
867          */
868         attnum = slot->tts_nvalid;
869         if (attnum == 0)
870         {
871                 /* Start from the first attribute */
872                 off = 0;
873                 slow = false;
874         }
875         else
876         {
877                 /* Restore state from previous execution */
878                 off = *offp;
879                 slow = TTS_SLOW(slot);
880         }
881
882         tp = (char *) tup + tup->t_hoff;
883
884         for (; attnum < natts; attnum++)
885         {
886                 Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
887
888                 if (hasnulls && att_isnull(attnum, bp))
889                 {
890                         values[attnum] = (Datum) 0;
891                         isnull[attnum] = true;
892                         slow = true;            /* can't use attcacheoff anymore */
893                         continue;
894                 }
895
896                 isnull[attnum] = false;
897
898                 if (!slow && thisatt->attcacheoff >= 0)
899                         off = thisatt->attcacheoff;
900                 else if (thisatt->attlen == -1)
901                 {
902                         /*
903                          * We can only cache the offset for a varlena attribute if the
904                          * offset is already suitably aligned, so that there would be no
905                          * pad bytes in any case: then the offset will be valid for either
906                          * an aligned or unaligned value.
907                          */
908                         if (!slow &&
909                                 off == att_align_nominal(off, thisatt->attalign))
910                                 thisatt->attcacheoff = off;
911                         else
912                         {
913                                 off = att_align_pointer(off, thisatt->attalign, -1,
914                                                                                 tp + off);
915                                 slow = true;
916                         }
917                 }
918                 else
919                 {
920                         /* not varlena, so safe to use att_align_nominal */
921                         off = att_align_nominal(off, thisatt->attalign);
922
923                         if (!slow)
924                                 thisatt->attcacheoff = off;
925                 }
926
927                 values[attnum] = fetchatt(thisatt, tp + off);
928
929                 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
930
931                 if (thisatt->attlen <= 0)
932                         slow = true;            /* can't use attcacheoff anymore */
933         }
934
935         /*
936          * Save state for next execution
937          */
938         slot->tts_nvalid = attnum;
939         *offp = off;
940         if (slow)
941                 slot->tts_flags |= TTS_FLAG_SLOW;
942         else
943                 slot->tts_flags &= ~TTS_FLAG_SLOW;
944 }
945
946
947 const TupleTableSlotOps TTSOpsVirtual = {
948         .base_slot_size = sizeof(VirtualTupleTableSlot),
949         .init = tts_virtual_init,
950         .release = tts_virtual_release,
951         .clear = tts_virtual_clear,
952         .getsomeattrs = tts_virtual_getsomeattrs,
953         .getsysattr = tts_virtual_getsysattr,
954         .materialize = tts_virtual_materialize,
955         .copyslot = tts_virtual_copyslot,
956
957         /*
958          * A virtual tuple table slot can not "own" a heap tuple or a minimal
959          * tuple.
960          */
961         .get_heap_tuple = NULL,
962         .get_minimal_tuple = NULL,
963         .copy_heap_tuple = tts_virtual_copy_heap_tuple,
964         .copy_minimal_tuple = tts_virtual_copy_minimal_tuple
965 };
966
967 const TupleTableSlotOps TTSOpsHeapTuple = {
968         .base_slot_size = sizeof(HeapTupleTableSlot),
969         .init = tts_heap_init,
970         .release = tts_heap_release,
971         .clear = tts_heap_clear,
972         .getsomeattrs = tts_heap_getsomeattrs,
973         .getsysattr = tts_heap_getsysattr,
974         .materialize = tts_heap_materialize,
975         .copyslot = tts_heap_copyslot,
976         .get_heap_tuple = tts_heap_get_heap_tuple,
977
978         /* A heap tuple table slot can not "own" a minimal tuple. */
979         .get_minimal_tuple = NULL,
980         .copy_heap_tuple = tts_heap_copy_heap_tuple,
981         .copy_minimal_tuple = tts_heap_copy_minimal_tuple
982 };
983
984 const TupleTableSlotOps TTSOpsMinimalTuple = {
985         .base_slot_size = sizeof(MinimalTupleTableSlot),
986         .init = tts_minimal_init,
987         .release = tts_minimal_release,
988         .clear = tts_minimal_clear,
989         .getsomeattrs = tts_minimal_getsomeattrs,
990         .getsysattr = tts_minimal_getsysattr,
991         .materialize = tts_minimal_materialize,
992         .copyslot = tts_minimal_copyslot,
993
994         /* A minimal tuple table slot can not "own" a heap tuple. */
995         .get_heap_tuple = NULL,
996         .get_minimal_tuple = tts_minimal_get_minimal_tuple,
997         .copy_heap_tuple = tts_minimal_copy_heap_tuple,
998         .copy_minimal_tuple = tts_minimal_copy_minimal_tuple
999 };
1000
1001 const TupleTableSlotOps TTSOpsBufferHeapTuple = {
1002         .base_slot_size = sizeof(BufferHeapTupleTableSlot),
1003         .init = tts_buffer_heap_init,
1004         .release = tts_buffer_heap_release,
1005         .clear = tts_buffer_heap_clear,
1006         .getsomeattrs = tts_buffer_heap_getsomeattrs,
1007         .getsysattr = tts_buffer_heap_getsysattr,
1008         .materialize = tts_buffer_heap_materialize,
1009         .copyslot = tts_buffer_heap_copyslot,
1010         .get_heap_tuple = tts_buffer_heap_get_heap_tuple,
1011
1012         /* A buffer heap tuple table slot can not "own" a minimal tuple. */
1013         .get_minimal_tuple = NULL,
1014         .copy_heap_tuple = tts_buffer_heap_copy_heap_tuple,
1015         .copy_minimal_tuple = tts_buffer_heap_copy_minimal_tuple
1016 };
1017
1018
1019 /* ----------------------------------------------------------------
1020  *                                tuple table create/delete functions
1021  * ----------------------------------------------------------------
1022  */
1023
1024 /* --------------------------------
1025  *              MakeTupleTableSlot
1026  *
1027  *              Basic routine to make an empty TupleTableSlot of given
1028  *              TupleTableSlotType. If tupleDesc is specified the slot's descriptor is
1029  *              fixed for it's lifetime, gaining some efficiency. If that's
1030  *              undesirable, pass NULL.
1031  * --------------------------------
1032  */
1033 TupleTableSlot *
1034 MakeTupleTableSlot(TupleDesc tupleDesc,
1035                                    const TupleTableSlotOps *tts_ops)
1036 {
1037         Size            basesz, allocsz;
1038         TupleTableSlot *slot;
1039         basesz = tts_ops->base_slot_size;
1040
1041         /*
1042          * When a fixed descriptor is specified, we can reduce overhead by
1043          * allocating the entire slot in one go.
1044          */
1045         if (tupleDesc)
1046                 allocsz = MAXALIGN(basesz) +
1047                         MAXALIGN(tupleDesc->natts * sizeof(Datum)) +
1048                         MAXALIGN(tupleDesc->natts * sizeof(bool));
1049         else
1050                 allocsz = basesz;
1051
1052         slot = palloc0(allocsz);
1053         /* const for optimization purposes, OK to modify at allocation time */
1054         *((const TupleTableSlotOps **) &slot->tts_ops) = tts_ops;
1055         slot->type = T_TupleTableSlot;
1056         slot->tts_flags |= TTS_FLAG_EMPTY;
1057         if (tupleDesc != NULL)
1058                 slot->tts_flags |= TTS_FLAG_FIXED;
1059         slot->tts_tupleDescriptor = tupleDesc;
1060         slot->tts_mcxt = CurrentMemoryContext;
1061         slot->tts_nvalid = 0;
1062
1063         if (tupleDesc != NULL)
1064         {
1065                 slot->tts_values = (Datum *)
1066                         (((char *) slot)
1067                          + MAXALIGN(basesz));
1068                 slot->tts_isnull = (bool *)
1069                         (((char *) slot)
1070                          + MAXALIGN(basesz)
1071                          + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
1072
1073                 PinTupleDesc(tupleDesc);
1074         }
1075
1076         /*
1077          * And allow slot type specific initialization.
1078          */
1079         slot->tts_ops->init(slot);
1080
1081         return slot;
1082 }
1083
1084 /* --------------------------------
1085  *              ExecAllocTableSlot
1086  *
1087  *              Create a tuple table slot within a tuple table (which is just a List).
1088  * --------------------------------
1089  */
1090 TupleTableSlot *
1091 ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
1092                                    const TupleTableSlotOps *tts_ops)
1093 {
1094         TupleTableSlot *slot = MakeTupleTableSlot(desc, tts_ops);
1095
1096         *tupleTable = lappend(*tupleTable, slot);
1097
1098         return slot;
1099 }
1100
1101 /* --------------------------------
1102  *              ExecResetTupleTable
1103  *
1104  *              This releases any resources (buffer pins, tupdesc refcounts)
1105  *              held by the tuple table, and optionally releases the memory
1106  *              occupied by the tuple table data structure.
1107  *              It is expected that this routine be called by EndPlan().
1108  * --------------------------------
1109  */
1110 void
1111 ExecResetTupleTable(List *tupleTable,   /* tuple table */
1112                                         bool shouldFree)        /* true if we should free memory */
1113 {
1114         ListCell   *lc;
1115
1116         foreach(lc, tupleTable)
1117         {
1118                 TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);
1119
1120                 /* Always release resources and reset the slot to empty */
1121                 ExecClearTuple(slot);
1122                 slot->tts_ops->release(slot);
1123                 if (slot->tts_tupleDescriptor)
1124                 {
1125                         ReleaseTupleDesc(slot->tts_tupleDescriptor);
1126                         slot->tts_tupleDescriptor = NULL;
1127                 }
1128
1129                 /* If shouldFree, release memory occupied by the slot itself */
1130                 if (shouldFree)
1131                 {
1132                         if (!TTS_FIXED(slot))
1133                         {
1134                                 if (slot->tts_values)
1135                                         pfree(slot->tts_values);
1136                                 if (slot->tts_isnull)
1137                                         pfree(slot->tts_isnull);
1138                         }
1139                         pfree(slot);
1140                 }
1141         }
1142
1143         /* If shouldFree, release the list structure */
1144         if (shouldFree)
1145                 list_free(tupleTable);
1146 }
1147
1148 /* --------------------------------
1149  *              MakeSingleTupleTableSlot
1150  *
1151  *              This is a convenience routine for operations that need a standalone
1152  *              TupleTableSlot not gotten from the main executor tuple table.  It makes
1153  *              a single slot of given TupleTableSlotType and initializes it to use the
1154  *              given tuple descriptor.
1155  * --------------------------------
1156  */
1157 TupleTableSlot *
1158 MakeSingleTupleTableSlot(TupleDesc tupdesc,
1159                                                  const TupleTableSlotOps *tts_ops)
1160 {
1161         TupleTableSlot *slot = MakeTupleTableSlot(tupdesc, tts_ops);
1162
1163         return slot;
1164 }
1165
1166 /* --------------------------------
1167  *              ExecDropSingleTupleTableSlot
1168  *
1169  *              Release a TupleTableSlot made with MakeSingleTupleTableSlot.
1170  *              DON'T use this on a slot that's part of a tuple table list!
1171  * --------------------------------
1172  */
1173 void
1174 ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
1175 {
1176         /* This should match ExecResetTupleTable's processing of one slot */
1177         Assert(IsA(slot, TupleTableSlot));
1178         ExecClearTuple(slot);
1179         slot->tts_ops->release(slot);
1180         if (slot->tts_tupleDescriptor)
1181                 ReleaseTupleDesc(slot->tts_tupleDescriptor);
1182         if (!TTS_FIXED(slot))
1183         {
1184                 if (slot->tts_values)
1185                         pfree(slot->tts_values);
1186                 if (slot->tts_isnull)
1187                         pfree(slot->tts_isnull);
1188         }
1189         pfree(slot);
1190 }
1191
1192
1193 /* ----------------------------------------------------------------
1194  *                                tuple table slot accessor functions
1195  * ----------------------------------------------------------------
1196  */
1197
1198 /* --------------------------------
1199  *              ExecSetSlotDescriptor
1200  *
1201  *              This function is used to set the tuple descriptor associated
1202  *              with the slot's tuple.  The passed descriptor must have lifespan
1203  *              at least equal to the slot's.  If it is a reference-counted descriptor
1204  *              then the reference count is incremented for as long as the slot holds
1205  *              a reference.
1206  * --------------------------------
1207  */
1208 void
1209 ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
1210                                           TupleDesc tupdesc)    /* new tuple descriptor */
1211 {
1212         Assert(!TTS_FIXED(slot));
1213
1214         /* For safety, make sure slot is empty before changing it */
1215         ExecClearTuple(slot);
1216
1217         /*
1218          * Release any old descriptor.  Also release old Datum/isnull arrays if
1219          * present (we don't bother to check if they could be re-used).
1220          */
1221         if (slot->tts_tupleDescriptor)
1222                 ReleaseTupleDesc(slot->tts_tupleDescriptor);
1223
1224         if (slot->tts_values)
1225                 pfree(slot->tts_values);
1226         if (slot->tts_isnull)
1227                 pfree(slot->tts_isnull);
1228
1229         /*
1230          * Install the new descriptor; if it's refcounted, bump its refcount.
1231          */
1232         slot->tts_tupleDescriptor = tupdesc;
1233         PinTupleDesc(tupdesc);
1234
1235         /*
1236          * Allocate Datum/isnull arrays of the appropriate size.  These must have
1237          * the same lifetime as the slot, so allocate in the slot's own context.
1238          */
1239         slot->tts_values = (Datum *)
1240                 MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(Datum));
1241         slot->tts_isnull = (bool *)
1242                 MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(bool));
1243 }
1244
1245 /* --------------------------------
1246  *              ExecStoreHeapTuple
1247  *
1248  *              This function is used to store an on-the-fly physical tuple into a specified
1249  *              slot in the tuple table.
1250  *
1251  *              tuple:  tuple to store
1252  *              slot:   TTSOpsHeapTuple type slot to store it in
1253  *              shouldFree: true if ExecClearTuple should pfree() the tuple
1254  *                                      when done with it
1255  *
1256  * shouldFree is normally set 'true' for tuples constructed on-the-fly.  But it
1257  * can be 'false' when the referenced tuple is held in a tuple table slot
1258  * belonging to a lower-level executor Proc node.  In this case the lower-level
1259  * slot retains ownership and responsibility for eventually releasing the
1260  * tuple.  When this method is used, we must be certain that the upper-level
1261  * Proc node will lose interest in the tuple sooner than the lower-level one
1262  * does!  If you're not certain, copy the lower-level tuple with heap_copytuple
1263  * and let the upper-level table slot assume ownership of the copy!
1264  *
1265  * Return value is just the passed-in slot pointer.
1266  *
1267  * If the target slot is not guaranteed to be TTSOpsHeapTuple type slot, use
1268  * the, more expensive, ExecForceStoreHeapTuple().
1269  * --------------------------------
1270  */
1271 TupleTableSlot *
1272 ExecStoreHeapTuple(HeapTuple tuple,
1273                                    TupleTableSlot *slot,
1274                                    bool shouldFree)
1275 {
1276         /*
1277          * sanity checks
1278          */
1279         Assert(tuple != NULL);
1280         Assert(slot != NULL);
1281         Assert(slot->tts_tupleDescriptor != NULL);
1282
1283         if (unlikely(!TTS_IS_HEAPTUPLE(slot)))
1284                 elog(ERROR, "trying to store a heap tuple into wrong type of slot");
1285         tts_heap_store_tuple(slot, tuple, shouldFree);
1286
1287         return slot;
1288 }
1289
1290 /* --------------------------------
1291  *              ExecStoreBufferHeapTuple
1292  *
1293  *              This function is used to store an on-disk physical tuple from a buffer
1294  *              into a specified slot in the tuple table.
1295  *
1296  *              tuple:  tuple to store
1297  *              slot:   TTSOpsBufferHeapTuple type slot to store it in
1298  *              buffer: disk buffer if tuple is in a disk page, else InvalidBuffer
1299  *
1300  * The tuple table code acquires a pin on the buffer which is held until the
1301  * slot is cleared, so that the tuple won't go away on us.
1302  *
1303  * Return value is just the passed-in slot pointer.
1304  *
1305  * If the target slot is not guaranteed to be TTSOpsBufferHeapTuple type slot,
1306  * use the, more expensive, ExecForceStoreHeapTuple().
1307  * --------------------------------
1308  */
1309 TupleTableSlot *
1310 ExecStoreBufferHeapTuple(HeapTuple tuple,
1311                                                  TupleTableSlot *slot,
1312                                                  Buffer buffer)
1313 {
1314         /*
1315          * sanity checks
1316          */
1317         Assert(tuple != NULL);
1318         Assert(slot != NULL);
1319         Assert(slot->tts_tupleDescriptor != NULL);
1320         Assert(BufferIsValid(buffer));
1321
1322         if (unlikely(!TTS_IS_BUFFERTUPLE(slot)))
1323                 elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
1324         tts_buffer_heap_store_tuple(slot, tuple, buffer);
1325
1326         return slot;
1327 }
1328
1329 /*
1330  * Store a minimal tuple into TTSOpsMinimalTuple type slot.
1331  *
1332  * If the target slot is not guaranteed to be TTSOpsMinimalTuple type slot,
1333  * use the, more expensive, ExecForceStoreMinimalTuple().
1334  */
1335 TupleTableSlot *
1336 ExecStoreMinimalTuple(MinimalTuple mtup,
1337                                           TupleTableSlot *slot,
1338                                           bool shouldFree)
1339 {
1340         /*
1341          * sanity checks
1342          */
1343         Assert(mtup != NULL);
1344         Assert(slot != NULL);
1345         Assert(slot->tts_tupleDescriptor != NULL);
1346
1347         if (unlikely(!TTS_IS_MINIMALTUPLE(slot)))
1348                 elog(ERROR, "trying to store a minimal tuple into wrong type of slot");
1349         tts_minimal_store_tuple(slot, mtup, shouldFree);
1350
1351         return slot;
1352 }
1353
1354 /*
1355  * Store a HeapTuple into any kind of slot, performing conversion if
1356  * necessary.
1357  */
1358 void
1359 ExecForceStoreHeapTuple(HeapTuple tuple,
1360                                                 TupleTableSlot *slot)
1361 {
1362         if (TTS_IS_HEAPTUPLE(slot))
1363         {
1364                 ExecStoreHeapTuple(tuple, slot, false);
1365         }
1366         else if (TTS_IS_BUFFERTUPLE(slot))
1367         {
1368                 MemoryContext oldContext;
1369                 BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
1370
1371                 ExecClearTuple(slot);
1372                 slot->tts_flags |= TTS_FLAG_SHOULDFREE;
1373                 slot->tts_flags &= ~TTS_FLAG_EMPTY;
1374                 oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
1375                 bslot->base.tuple = heap_copytuple(tuple);
1376                 MemoryContextSwitchTo(oldContext);
1377         }
1378         else
1379         {
1380                 ExecClearTuple(slot);
1381                 heap_deform_tuple(tuple, slot->tts_tupleDescriptor,
1382                                                   slot->tts_values, slot->tts_isnull);
1383                 ExecStoreVirtualTuple(slot);
1384         }
1385 }
1386
1387 /*
1388  * Store a MinimalTuple into any kind of slot, performing conversion if
1389  * necessary.
1390  */
1391 void
1392 ExecForceStoreMinimalTuple(MinimalTuple mtup,
1393                                                    TupleTableSlot *slot,
1394                                                    bool shouldFree)
1395 {
1396         if (TTS_IS_MINIMALTUPLE(slot))
1397         {
1398                 tts_minimal_store_tuple(slot, mtup, shouldFree);
1399         }
1400         else
1401         {
1402                 HeapTupleData htup;
1403
1404                 ExecClearTuple(slot);
1405
1406                 htup.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
1407                 htup.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
1408                 heap_deform_tuple(&htup, slot->tts_tupleDescriptor,
1409                                                   slot->tts_values, slot->tts_isnull);
1410                 ExecStoreVirtualTuple(slot);
1411         }
1412 }
1413
1414 /* --------------------------------
1415  *              ExecStoreVirtualTuple
1416  *                      Mark a slot as containing a virtual tuple.
1417  *
1418  * The protocol for loading a slot with virtual tuple data is:
1419  *              * Call ExecClearTuple to mark the slot empty.
1420  *              * Store data into the Datum/isnull arrays.
1421  *              * Call ExecStoreVirtualTuple to mark the slot valid.
1422  * This is a bit unclean but it avoids one round of data copying.
1423  * --------------------------------
1424  */
1425 TupleTableSlot *
1426 ExecStoreVirtualTuple(TupleTableSlot *slot)
1427 {
1428         /*
1429          * sanity checks
1430          */
1431         Assert(slot != NULL);
1432         Assert(slot->tts_tupleDescriptor != NULL);
1433         Assert(TTS_EMPTY(slot));
1434
1435         slot->tts_flags &= ~TTS_FLAG_EMPTY;
1436         slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
1437
1438         return slot;
1439 }
1440
1441 /* --------------------------------
1442  *              ExecStoreAllNullTuple
1443  *                      Set up the slot to contain a null in every column.
1444  *
1445  * At first glance this might sound just like ExecClearTuple, but it's
1446  * entirely different: the slot ends up full, not empty.
1447  * --------------------------------
1448  */
1449 TupleTableSlot *
1450 ExecStoreAllNullTuple(TupleTableSlot *slot)
1451 {
1452         /*
1453          * sanity checks
1454          */
1455         Assert(slot != NULL);
1456         Assert(slot->tts_tupleDescriptor != NULL);
1457
1458         /* Clear any old contents */
1459         ExecClearTuple(slot);
1460
1461         /*
1462          * Fill all the columns of the virtual tuple with nulls
1463          */
1464         MemSet(slot->tts_values, 0,
1465                    slot->tts_tupleDescriptor->natts * sizeof(Datum));
1466         memset(slot->tts_isnull, true,
1467                    slot->tts_tupleDescriptor->natts * sizeof(bool));
1468
1469         return ExecStoreVirtualTuple(slot);
1470 }
1471
1472 /*
1473  * ExecFetchSlotHeapTuple - fetch HeapTuple representing the slot's content
1474  *
1475  * The returned HeapTuple represents the slot's content as closely as
1476  * possible.
1477  *
1478  * If materialize is true, the contents of the slots will be made independent
1479  * from the underlying storage (i.e. all buffer pins are released, memory is
1480  * allocated in the slot's context).
1481  *
1482  * If shouldFree is not-NULL it'll be set to true if the returned tuple has
1483  * been allocated in the calling memory context, and must be freed by the
1484  * caller (via explicit pfree() or a memory context reset).
1485  *
1486  * NB: If materialize is true, modifications of the returned tuple are
1487  * allowed. But it depends on the type of the slot whether such modifications
1488  * will also affect the slot's contents. While that is not the nicest
1489  * behaviour, all such modifcations are in the process of being removed.
1490  */
1491 HeapTuple
1492 ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
1493 {
1494         /*
1495          * sanity checks
1496          */
1497         Assert(slot != NULL);
1498         Assert(!TTS_EMPTY(slot));
1499
1500         /* Materialize the tuple so that the slot "owns" it, if requested. */
1501         if (materialize)
1502                 slot->tts_ops->materialize(slot);
1503
1504         if (slot->tts_ops->get_heap_tuple == NULL)
1505         {
1506                 if (shouldFree)
1507                         *shouldFree = true;
1508                 return slot->tts_ops->copy_heap_tuple(slot);
1509         }
1510         else
1511         {
1512                 if (shouldFree)
1513                         *shouldFree = false;
1514                 return slot->tts_ops->get_heap_tuple(slot);
1515         }
1516 }
1517
1518 /* --------------------------------
1519  *              ExecFetchSlotMinimalTuple
1520  *                      Fetch the slot's minimal physical tuple.
1521  *
1522  *              If the given tuple table slot can hold a minimal tuple, indicated by a
1523  *              non-NULL get_minimal_tuple callback, the function returns the minimal
1524  *              tuple returned by that callback. It assumes that the minimal tuple
1525  *              returned by the callback is "owned" by the slot i.e. the slot is
1526  *              responsible for freeing the memory consumed by the tuple. Hence it sets
1527  *              *shouldFree to false, indicating that the caller should not free the
1528  *              memory consumed by the minimal tuple. In this case the returned minimal
1529  *              tuple should be considered as read-only.
1530  *
1531  *              If that callback is not supported, it calls copy_minimal_tuple callback
1532  *              which is expected to return a copy of minimal tuple represnting the
1533  *              contents of the slot. In this case *shouldFree is set to true,
1534  *              indicating the caller that it should free the memory consumed by the
1535  *              minimal tuple. In this case the returned minimal tuple may be written
1536  *              up.
1537  * --------------------------------
1538  */
1539 MinimalTuple
1540 ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
1541                                                   bool *shouldFree)
1542 {
1543         /*
1544          * sanity checks
1545          */
1546         Assert(slot != NULL);
1547         Assert(!TTS_EMPTY(slot));
1548
1549         if (slot->tts_ops->get_minimal_tuple)
1550         {
1551                 if (shouldFree)
1552                         *shouldFree = false;
1553                 return slot->tts_ops->get_minimal_tuple(slot);
1554         }
1555         else
1556         {
1557                 if (shouldFree)
1558                         *shouldFree = true;
1559                 return slot->tts_ops->copy_minimal_tuple(slot);
1560         }
1561 }
1562
1563 /* --------------------------------
1564  *              ExecFetchSlotHeapTupleDatum
1565  *                      Fetch the slot's tuple as a composite-type Datum.
1566  *
1567  *              The result is always freshly palloc'd in the caller's memory context.
1568  * --------------------------------
1569  */
1570 Datum
1571 ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
1572 {
1573         HeapTuple       tup;
1574         TupleDesc       tupdesc;
1575         bool            shouldFree;
1576         Datum           ret;
1577
1578         /* Fetch slot's contents in regular-physical-tuple form */
1579         tup = ExecFetchSlotHeapTuple(slot, false, &shouldFree);
1580         tupdesc = slot->tts_tupleDescriptor;
1581
1582         /* Convert to Datum form */
1583         ret = heap_copy_tuple_as_datum(tup, tupdesc);
1584
1585         if (shouldFree)
1586                 pfree(tup);
1587
1588         return ret;
1589 }
1590
1591 /* ----------------------------------------------------------------
1592  *                              convenience initialization routines
1593  * ----------------------------------------------------------------
1594  */
1595
1596 /* ----------------
1597  *              ExecInitResultTypeTL
1598  *
1599  *              Initialize result type, using the plan node's targetlist.
1600  * ----------------
1601  */
1602 void
1603 ExecInitResultTypeTL(PlanState *planstate)
1604 {
1605         TupleDesc       tupDesc = ExecTypeFromTL(planstate->plan->targetlist);
1606
1607         tupDesc = ExecTypeFromTL(planstate->plan->targetlist);
1608         planstate->ps_ResultTupleDesc = tupDesc;
1609 }
1610
1611 /* --------------------------------
1612  *              ExecInit{Result,Scan,Extra}TupleSlot[TL]
1613  *
1614  *              These are convenience routines to initialize the specified slot
1615  *              in nodes inheriting the appropriate state.  ExecInitExtraTupleSlot
1616  *              is used for initializing special-purpose slots.
1617  * --------------------------------
1618  */
1619
1620 /* ----------------
1621  *              ExecInitResultTupleSlotTL
1622  *
1623  *              Initialize result tuple slot, using the tuple descriptor previously
1624  *              computed with ExecInitResultTypeTL().
1625  * ----------------
1626  */
1627 void
1628 ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
1629 {
1630         TupleTableSlot *slot;
1631
1632         slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
1633                                                           planstate->ps_ResultTupleDesc, tts_ops);
1634         planstate->ps_ResultTupleSlot = slot;
1635
1636         planstate->resultopsfixed = planstate->ps_ResultTupleDesc != NULL;
1637         planstate->resultops = tts_ops;
1638         planstate->resultopsset = true;
1639 }
1640
1641 /* ----------------
1642  *              ExecInitResultTupleSlotTL
1643  *
1644  *              Initialize result tuple slot, using the plan node's targetlist.
1645  * ----------------
1646  */
1647 void
1648 ExecInitResultTupleSlotTL(PlanState *planstate,
1649                                                   const TupleTableSlotOps *tts_ops)
1650 {
1651         ExecInitResultTypeTL(planstate);
1652         ExecInitResultSlot(planstate, tts_ops);
1653 }
1654
1655 /* ----------------
1656  *              ExecInitScanTupleSlot
1657  * ----------------
1658  */
1659 void
1660 ExecInitScanTupleSlot(EState *estate, ScanState *scanstate,
1661                                           TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
1662 {
1663         scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
1664                                                                                                          tupledesc, tts_ops);
1665         scanstate->ps.scandesc = tupledesc;
1666         scanstate->ps.scanopsfixed = tupledesc != NULL;
1667         scanstate->ps.scanops = tts_ops;
1668         scanstate->ps.scanopsset = true;
1669 }
1670
1671 /* ----------------
1672  *              ExecInitExtraTupleSlot
1673  *
1674  * Return a newly created slot. If tupledesc is non-NULL the slot will have
1675  * that as its fixed tupledesc. Otherwise the caller needs to use
1676  * ExecSetSlotDescriptor() to set the descriptor before use.
1677  * ----------------
1678  */
1679 TupleTableSlot *
1680 ExecInitExtraTupleSlot(EState *estate,
1681                                            TupleDesc tupledesc,
1682                                            const TupleTableSlotOps *tts_ops)
1683 {
1684         return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc, tts_ops);
1685 }
1686
1687 /* ----------------
1688  *              ExecInitNullTupleSlot
1689  *
1690  * Build a slot containing an all-nulls tuple of the given type.
1691  * This is used as a substitute for an input tuple when performing an
1692  * outer join.
1693  * ----------------
1694  */
1695 TupleTableSlot *
1696 ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
1697                                           const TupleTableSlotOps *tts_ops)
1698 {
1699         TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_ops);
1700
1701         return ExecStoreAllNullTuple(slot);
1702 }
1703
1704 /* ---------------------------------------------------------------
1705  *      Routines for setting/accessing attributes in a slot.
1706  * ---------------------------------------------------------------
1707  */
1708
1709 /*
1710  * Fill in missing values for a TupleTableSlot.
1711  *
1712  * This is only exposed because it's needed for JIT compiled tuple
1713  * deforming. That exception aside, there should be no callers outside of this
1714  * file.
1715  */
1716 void
1717 slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
1718 {
1719         AttrMissing *attrmiss = NULL;
1720
1721         if (slot->tts_tupleDescriptor->constr)
1722                 attrmiss = slot->tts_tupleDescriptor->constr->missing;
1723
1724         if (!attrmiss)
1725         {
1726                 /* no missing values array at all, so just fill everything in as NULL */
1727                 memset(slot->tts_values + startAttNum, 0,
1728                            (lastAttNum - startAttNum) * sizeof(Datum));
1729                 memset(slot->tts_isnull + startAttNum, 1,
1730                            (lastAttNum - startAttNum) * sizeof(bool));
1731         }
1732         else
1733         {
1734                 int                     missattnum;
1735
1736                 /* if there is a missing values array we must process them one by one */
1737                 for (missattnum = startAttNum;
1738                          missattnum < lastAttNum;
1739                          missattnum++)
1740                 {
1741                         slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
1742                         slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
1743                 }
1744
1745         }
1746 }
1747
1748 /*
1749  * slot_getsomeattrs_int - workhorse for slot_getsomeattrs()
1750  */
1751 void
1752 slot_getsomeattrs_int(TupleTableSlot *slot, int attnum)
1753 {
1754         /* Check for caller errors */
1755         Assert(slot->tts_nvalid < attnum); /* slot_getsomeattr checked */
1756         Assert(attnum > 0);
1757
1758         if (unlikely(attnum > slot->tts_tupleDescriptor->natts))
1759                 elog(ERROR, "invalid attribute number %d", attnum);
1760
1761         /* Fetch as many attributes as possible from the underlying tuple. */
1762         slot->tts_ops->getsomeattrs(slot, attnum);
1763
1764         /*
1765          * If the underlying tuple doesn't have enough attributes, tuple descriptor
1766          * must have the missing attributes.
1767          */
1768         if (unlikely(slot->tts_nvalid < attnum))
1769         {
1770                 slot_getmissingattrs(slot, slot->tts_nvalid, attnum);
1771                 slot->tts_nvalid = attnum;
1772         }
1773 }
1774
1775 /* ----------------------------------------------------------------
1776  *              ExecTypeFromTL
1777  *
1778  *              Generate a tuple descriptor for the result tuple of a targetlist.
1779  *              (A parse/plan tlist must be passed, not an ExprState tlist.)
1780  *              Note that resjunk columns, if any, are included in the result.
1781  *
1782  *              Currently there are about 4 different places where we create
1783  *              TupleDescriptors.  They should all be merged, or perhaps
1784  *              be rewritten to call BuildDesc().
1785  * ----------------------------------------------------------------
1786  */
1787 TupleDesc
1788 ExecTypeFromTL(List *targetList)
1789 {
1790         return ExecTypeFromTLInternal(targetList, false);
1791 }
1792
1793 /* ----------------------------------------------------------------
1794  *              ExecCleanTypeFromTL
1795  *
1796  *              Same as above, but resjunk columns are omitted from the result.
1797  * ----------------------------------------------------------------
1798  */
1799 TupleDesc
1800 ExecCleanTypeFromTL(List *targetList)
1801 {
1802         return ExecTypeFromTLInternal(targetList, true);
1803 }
1804
1805 static TupleDesc
1806 ExecTypeFromTLInternal(List *targetList, bool skipjunk)
1807 {
1808         TupleDesc       typeInfo;
1809         ListCell   *l;
1810         int                     len;
1811         int                     cur_resno = 1;
1812
1813         if (skipjunk)
1814                 len = ExecCleanTargetListLength(targetList);
1815         else
1816                 len = ExecTargetListLength(targetList);
1817         typeInfo = CreateTemplateTupleDesc(len);
1818
1819         foreach(l, targetList)
1820         {
1821                 TargetEntry *tle = lfirst(l);
1822
1823                 if (skipjunk && tle->resjunk)
1824                         continue;
1825                 TupleDescInitEntry(typeInfo,
1826                                                    cur_resno,
1827                                                    tle->resname,
1828                                                    exprType((Node *) tle->expr),
1829                                                    exprTypmod((Node *) tle->expr),
1830                                                    0);
1831                 TupleDescInitEntryCollation(typeInfo,
1832                                                                         cur_resno,
1833                                                                         exprCollation((Node *) tle->expr));
1834                 cur_resno++;
1835         }
1836
1837         return typeInfo;
1838 }
1839
1840 /*
1841  * ExecTypeFromExprList - build a tuple descriptor from a list of Exprs
1842  *
1843  * This is roughly like ExecTypeFromTL, but we work from bare expressions
1844  * not TargetEntrys.  No names are attached to the tupledesc's columns.
1845  */
1846 TupleDesc
1847 ExecTypeFromExprList(List *exprList)
1848 {
1849         TupleDesc       typeInfo;
1850         ListCell   *lc;
1851         int                     cur_resno = 1;
1852
1853         typeInfo = CreateTemplateTupleDesc(list_length(exprList));
1854
1855         foreach(lc, exprList)
1856         {
1857                 Node       *e = lfirst(lc);
1858
1859                 TupleDescInitEntry(typeInfo,
1860                                                    cur_resno,
1861                                                    NULL,
1862                                                    exprType(e),
1863                                                    exprTypmod(e),
1864                                                    0);
1865                 TupleDescInitEntryCollation(typeInfo,
1866                                                                         cur_resno,
1867                                                                         exprCollation(e));
1868                 cur_resno++;
1869         }
1870
1871         return typeInfo;
1872 }
1873
1874 /*
1875  * ExecTypeSetColNames - set column names in a TupleDesc
1876  *
1877  * Column names must be provided as an alias list (list of String nodes).
1878  *
1879  * For some callers, the supplied tupdesc has a named rowtype (not RECORD)
1880  * and it is moderately likely that the alias list matches the column names
1881  * already present in the tupdesc.  If we do change any column names then
1882  * we must reset the tupdesc's type to anonymous RECORD; but we avoid doing
1883  * so if no names change.
1884  */
1885 void
1886 ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
1887 {
1888         bool            modified = false;
1889         int                     colno = 0;
1890         ListCell   *lc;
1891
1892         foreach(lc, namesList)
1893         {
1894                 char       *cname = strVal(lfirst(lc));
1895                 Form_pg_attribute attr;
1896
1897                 /* Guard against too-long names list */
1898                 if (colno >= typeInfo->natts)
1899                         break;
1900                 attr = TupleDescAttr(typeInfo, colno);
1901                 colno++;
1902
1903                 /* Ignore empty aliases (these must be for dropped columns) */
1904                 if (cname[0] == '\0')
1905                         continue;
1906
1907                 /* Change tupdesc only if alias is actually different */
1908                 if (strcmp(cname, NameStr(attr->attname)) != 0)
1909                 {
1910                         namestrcpy(&(attr->attname), cname);
1911                         modified = true;
1912                 }
1913         }
1914
1915         /* If we modified the tupdesc, it's now a new record type */
1916         if (modified)
1917         {
1918                 typeInfo->tdtypeid = RECORDOID;
1919                 typeInfo->tdtypmod = -1;
1920         }
1921 }
1922
1923 /*
1924  * BlessTupleDesc - make a completed tuple descriptor useful for SRFs
1925  *
1926  * Rowtype Datums returned by a function must contain valid type information.
1927  * This happens "for free" if the tupdesc came from a relcache entry, but
1928  * not if we have manufactured a tupdesc for a transient RECORD datatype.
1929  * In that case we have to notify typcache.c of the existence of the type.
1930  */
1931 TupleDesc
1932 BlessTupleDesc(TupleDesc tupdesc)
1933 {
1934         if (tupdesc->tdtypeid == RECORDOID &&
1935                 tupdesc->tdtypmod < 0)
1936                 assign_record_type_typmod(tupdesc);
1937
1938         return tupdesc;                         /* just for notational convenience */
1939 }
1940
1941 /*
1942  * TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the
1943  * supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
1944  * to produce a properly formed tuple.
1945  */
1946 AttInMetadata *
1947 TupleDescGetAttInMetadata(TupleDesc tupdesc)
1948 {
1949         int                     natts = tupdesc->natts;
1950         int                     i;
1951         Oid                     atttypeid;
1952         Oid                     attinfuncid;
1953         FmgrInfo   *attinfuncinfo;
1954         Oid                *attioparams;
1955         int32      *atttypmods;
1956         AttInMetadata *attinmeta;
1957
1958         attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
1959
1960         /* "Bless" the tupledesc so that we can make rowtype datums with it */
1961         attinmeta->tupdesc = BlessTupleDesc(tupdesc);
1962
1963         /*
1964          * Gather info needed later to call the "in" function for each attribute
1965          */
1966         attinfuncinfo = (FmgrInfo *) palloc0(natts * sizeof(FmgrInfo));
1967         attioparams = (Oid *) palloc0(natts * sizeof(Oid));
1968         atttypmods = (int32 *) palloc0(natts * sizeof(int32));
1969
1970         for (i = 0; i < natts; i++)
1971         {
1972                 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1973
1974                 /* Ignore dropped attributes */
1975                 if (!att->attisdropped)
1976                 {
1977                         atttypeid = att->atttypid;
1978                         getTypeInputInfo(atttypeid, &attinfuncid, &attioparams[i]);
1979                         fmgr_info(attinfuncid, &attinfuncinfo[i]);
1980                         atttypmods[i] = att->atttypmod;
1981                 }
1982         }
1983         attinmeta->attinfuncs = attinfuncinfo;
1984         attinmeta->attioparams = attioparams;
1985         attinmeta->atttypmods = atttypmods;
1986
1987         return attinmeta;
1988 }
1989
1990 /*
1991  * BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
1992  * values is an array of C strings, one for each attribute of the return tuple.
1993  * A NULL string pointer indicates we want to create a NULL field.
1994  */
1995 HeapTuple
1996 BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
1997 {
1998         TupleDesc       tupdesc = attinmeta->tupdesc;
1999         int                     natts = tupdesc->natts;
2000         Datum      *dvalues;
2001         bool       *nulls;
2002         int                     i;
2003         HeapTuple       tuple;
2004
2005         dvalues = (Datum *) palloc(natts * sizeof(Datum));
2006         nulls = (bool *) palloc(natts * sizeof(bool));
2007
2008         /*
2009          * Call the "in" function for each non-dropped attribute, even for nulls,
2010          * to support domains.
2011          */
2012         for (i = 0; i < natts; i++)
2013         {
2014                 if (!TupleDescAttr(tupdesc, i)->attisdropped)
2015                 {
2016                         /* Non-dropped attributes */
2017                         dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i],
2018                                                                                    values[i],
2019                                                                                    attinmeta->attioparams[i],
2020                                                                                    attinmeta->atttypmods[i]);
2021                         if (values[i] != NULL)
2022                                 nulls[i] = false;
2023                         else
2024                                 nulls[i] = true;
2025                 }
2026                 else
2027                 {
2028                         /* Handle dropped attributes by setting to NULL */
2029                         dvalues[i] = (Datum) 0;
2030                         nulls[i] = true;
2031                 }
2032         }
2033
2034         /*
2035          * Form a tuple
2036          */
2037         tuple = heap_form_tuple(tupdesc, dvalues, nulls);
2038
2039         /*
2040          * Release locally palloc'd space.  XXX would probably be good to pfree
2041          * values of pass-by-reference datums, as well.
2042          */
2043         pfree(dvalues);
2044         pfree(nulls);
2045
2046         return tuple;
2047 }
2048
2049 /*
2050  * HeapTupleHeaderGetDatum - convert a HeapTupleHeader pointer to a Datum.
2051  *
2052  * This must *not* get applied to an on-disk tuple; the tuple should be
2053  * freshly made by heap_form_tuple or some wrapper routine for it (such as
2054  * BuildTupleFromCStrings).  Be sure also that the tupledesc used to build
2055  * the tuple has a properly "blessed" rowtype.
2056  *
2057  * Formerly this was a macro equivalent to PointerGetDatum, relying on the
2058  * fact that heap_form_tuple fills in the appropriate tuple header fields
2059  * for a composite Datum.  However, we now require that composite Datums not
2060  * contain any external TOAST pointers.  We do not want heap_form_tuple itself
2061  * to enforce that; more specifically, the rule applies only to actual Datums
2062  * and not to HeapTuple structures.  Therefore, HeapTupleHeaderGetDatum is
2063  * now a function that detects whether there are externally-toasted fields
2064  * and constructs a new tuple with inlined fields if so.  We still need
2065  * heap_form_tuple to insert the Datum header fields, because otherwise this
2066  * code would have no way to obtain a tupledesc for the tuple.
2067  *
2068  * Note that if we do build a new tuple, it's palloc'd in the current
2069  * memory context.  Beware of code that changes context between the initial
2070  * heap_form_tuple/etc call and calling HeapTuple(Header)GetDatum.
2071  *
2072  * For performance-critical callers, it could be worthwhile to take extra
2073  * steps to ensure that there aren't TOAST pointers in the output of
2074  * heap_form_tuple to begin with.  It's likely however that the costs of the
2075  * typcache lookup and tuple disassembly/reassembly are swamped by TOAST
2076  * dereference costs, so that the benefits of such extra effort would be
2077  * minimal.
2078  *
2079  * XXX it would likely be better to create wrapper functions that produce
2080  * a composite Datum from the field values in one step.  However, there's
2081  * enough code using the existing APIs that we couldn't get rid of this
2082  * hack anytime soon.
2083  */
2084 Datum
2085 HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
2086 {
2087         Datum           result;
2088         TupleDesc       tupDesc;
2089
2090         /* No work if there are no external TOAST pointers in the tuple */
2091         if (!HeapTupleHeaderHasExternal(tuple))
2092                 return PointerGetDatum(tuple);
2093
2094         /* Use the type data saved by heap_form_tuple to look up the rowtype */
2095         tupDesc = lookup_rowtype_tupdesc(HeapTupleHeaderGetTypeId(tuple),
2096                                                                          HeapTupleHeaderGetTypMod(tuple));
2097
2098         /* And do the flattening */
2099         result = toast_flatten_tuple_to_datum(tuple,
2100                                                                                   HeapTupleHeaderGetDatumLength(tuple),
2101                                                                                   tupDesc);
2102
2103         ReleaseTupleDesc(tupDesc);
2104
2105         return result;
2106 }
2107
2108
2109 /*
2110  * Functions for sending tuples to the frontend (or other specified destination)
2111  * as though it is a SELECT result. These are used by utility commands that
2112  * need to project directly to the destination and don't need or want full
2113  * table function capability. Currently used by EXPLAIN and SHOW ALL.
2114  */
2115 TupOutputState *
2116 begin_tup_output_tupdesc(DestReceiver *dest,
2117                                                  TupleDesc tupdesc,
2118                                                  const TupleTableSlotOps *tts_ops)
2119 {
2120         TupOutputState *tstate;
2121
2122         tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
2123
2124         tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2125         tstate->dest = dest;
2126
2127         tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2128
2129         return tstate;
2130 }
2131
2132 /*
2133  * write a single tuple
2134  */
2135 void
2136 do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
2137 {
2138         TupleTableSlot *slot = tstate->slot;
2139         int                     natts = slot->tts_tupleDescriptor->natts;
2140
2141         /* make sure the slot is clear */
2142         ExecClearTuple(slot);
2143
2144         /* insert data */
2145         memcpy(slot->tts_values, values, natts * sizeof(Datum));
2146         memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2147
2148         /* mark slot as containing a virtual tuple */
2149         ExecStoreVirtualTuple(slot);
2150
2151         /* send the tuple to the receiver */
2152         (void) tstate->dest->receiveSlot(slot, tstate->dest);
2153
2154         /* clean up */
2155         ExecClearTuple(slot);
2156 }
2157
2158 /*
2159  * write a chunk of text, breaking at newline characters
2160  *
2161  * Should only be used with a single-TEXT-attribute tupdesc.
2162  */
2163 void
2164 do_text_output_multiline(TupOutputState *tstate, const char *txt)
2165 {
2166         Datum           values[1];
2167         bool            isnull[1] = {false};
2168
2169         while (*txt)
2170         {
2171                 const char *eol;
2172                 int                     len;
2173
2174                 eol = strchr(txt, '\n');
2175                 if (eol)
2176                 {
2177                         len = eol - txt;
2178                         eol++;
2179                 }
2180                 else
2181                 {
2182                         len = strlen(txt);
2183                         eol = txt + len;
2184                 }
2185
2186                 values[0] = PointerGetDatum(cstring_to_text_with_len(txt, len));
2187                 do_tup_output(tstate, values, isnull);
2188                 pfree(DatumGetPointer(values[0]));
2189                 txt = eol;
2190         }
2191 }
2192
2193 void
2194 end_tup_output(TupOutputState *tstate)
2195 {
2196         tstate->dest->rShutdown(tstate->dest);
2197         /* note that destroying the dest is not ours to do */
2198         ExecDropSingleTupleTableSlot(tstate->slot);
2199         pfree(tstate);
2200 }