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