PostgreSQL Source Code  git master
execTuples.c
Go to the documentation of this file.
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);
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 
87 
88 
89 /*
90  * TupleTableSlotOps implementations.
91  */
92 
93 /*
94  * TupleTableSlotOps implementation for VirtualTupleTableSlot.
95  */
96 static void
98 {
99 }
100 
101 static void
103 {
104 }
105 
106 static void
108 {
109  if (unlikely(TTS_SHOULDFREE(slot)))
110  {
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;
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
131 {
132  elog(ERROR, "getsomeattrs is not required to be called on a virtual tuple table slot");
133 }
134 
135 static Datum
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
152 {
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 &&
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);
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 &&
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  */
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
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
269 {
270  Assert(!TTS_EMPTY(slot));
271 
273  slot->tts_values,
274  slot->tts_isnull);
275 
276 }
277 
278 static MinimalTuple
280 {
281  Assert(!TTS_EMPTY(slot));
282 
284  slot->tts_values,
285  slot->tts_isnull);
286 }
287 
288 
289 /*
290  * TupleTableSlotOps implementation for HeapTupleTableSlot.
291  */
292 
293 static void
295 {
296 }
297 
298 static void
300 {
301 }
302 
303 static void
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;
318  hslot->off = 0;
319  hslot->tuple = NULL;
320 }
321 
322 static void
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
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 
354 
355  oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
356 
357  if (!hslot->tuple)
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
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
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
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
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)
444 }
445 
446 
447 /*
448  * TupleTableSlotOps implementation for MinimalTupleTableSlot.
449  */
450 
451 static void
453 {
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
465 {
466 }
467 
468 static void
470 {
472 
473  if (TTS_SHOULDFREE(slot))
474  {
476  slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
477  }
478 
479  slot->tts_nvalid = 0;
480  slot->tts_flags |= TTS_FLAG_EMPTY;
482  mslot->off = 0;
483  mslot->mintuple = NULL;
484 }
485 
486 static void
488 {
490 
491  Assert(!TTS_EMPTY(slot));
492 
493  slot_deform_heap_tuple(slot, mslot->tuple, &mslot->off, natts);
494 }
495 
496 static Datum
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
506 {
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 
517  oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
518 
519  if (!mslot->mintuple)
520  {
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
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
565 {
567 
568  if (!mslot->mintuple)
570 
571  return mslot->mintuple;
572 }
573 
574 static HeapTuple
576 {
578 
579  if (!mslot->mintuple)
581 
583 }
584 
585 static MinimalTuple
587 {
589 
590  if (!mslot->mintuple)
592 
593  return heap_copy_minimal_tuple(mslot->mintuple);
594 }
595 
596 static void
598 {
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)
618  else
619  Assert(!TTS_SHOULDFREE(slot));
620 }
621 
622 
623 /*
624  * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
625  */
626 
627 static void
629 {
630 }
631 
632 static void
634 {
635 }
636 
637 static void
639 {
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;
664  bslot->base.tuple = NULL;
665  bslot->base.off = 0;
666  bslot->buffer = InvalidBuffer;
667 }
668 
669 static void
671 {
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
681 {
683 
684  return heap_getsysattr(bslot->base.tuple, attnum,
685  slot->tts_tupleDescriptor, isnull);
686 }
687 
688 static void
690 {
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 
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  */
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
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
785 {
787 
788  Assert(!TTS_EMPTY(slot));
789 
790  if (!bslot->base.tuple)
792 
793  return bslot->base.tuple;
794 }
795 
796 static HeapTuple
798 {
800 
801  Assert(!TTS_EMPTY(slot));
802 
803  if (!bslot->base.tuple)
805 
806  return heap_copytuple(bslot->base.tuple);
807 }
808 
809 static MinimalTuple
811 {
813 
814  Assert(!TTS_EMPTY(slot));
815 
816  if (!bslot->base.tuple)
818 
820 }
821 
822 static inline void
824  Buffer buffer, bool transfer_pin)
825 {
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
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 = {
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 = {
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 = {
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 = {
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  */
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;
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  */
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  {
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  {
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  */
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
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)
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)
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  */
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  */
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  */
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  */
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
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;
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);
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
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);
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  */
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  */
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
1571 {
1572  HeapTupleData tuple = {0};
1573  HeapTupleHeader td;
1574 
1575  td = DatumGetHeapTupleHeader(data);
1576 
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  */
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
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
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
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
1764  const TupleTableSlotOps *tts_ops)
1765 {
1766  ExecInitResultTypeTL(planstate);
1767  ExecInitResultSlot(planstate, tts_ops);
1768 }
1769 
1770 /* ----------------
1771  * ExecInitScanTupleSlot
1772  * ----------------
1773  */
1774 void
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  */
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  */
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
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
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
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
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 *
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
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
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 */
2211  HeapTupleHeaderGetTypMod(tuple));
2212 
2213  /* And do the flattening */
2214  result = toast_flatten_tuple_to_datum(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  */
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
2310 {
2311  tstate->dest->rShutdown(tstate->dest);
2312  /* note that destroying the dest is not ours to do */
2314  pfree(tstate);
2315 }
static void tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: execTuples.c:742
#define TTS_FIXED(slot)
Definition: tuptable.h:109
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
Oid tts_tableOid
Definition: tuptable.h:131
static void tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer, bool transfer_pin)
Definition: execTuples.c:823
Definition: fmgr.h:56
int ExecTargetListLength(List *targetlist)
Definition: execUtils.c:1090
#define TTS_FLAG_EMPTY
Definition: tuptable.h:96
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1410
#define likely(x)
Definition: c.h:207
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1795
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:146
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: postgres.h:322
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1652
static void tts_minimal_materialize(TupleTableSlot *slot)
Definition: execTuples.c:505
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:426
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
Definition: htup_details.h:177
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
TupleDesc ExecCleanTypeFromTL(List *targetList)
Definition: execTuples.c:1915
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
Definition: execTuples.c:1540
HeapTuple(* copy_heap_tuple)(TupleTableSlot *slot)
Definition: tuptable.h:206
static HeapTuple tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
Definition: execTuples.c:784
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1202
static void tts_heap_materialize(TupleTableSlot *slot)
Definition: execTuples.c:342
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
Definition: execTuples.c:1921
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
#define TTS_EMPTY(slot)
Definition: tuptable.h:97
#define att_isnull(ATT, BITS)
Definition: tupmacs.h:23
#define PointerGetDatum(X)
Definition: postgres.h:556
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define TTS_SHOULDFREE(slot)
Definition: tuptable.h:101
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
Definition: execTuples.c:1656
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
const TupleTableSlotOps TTSOpsBufferHeapTuple
Definition: execTuples.c:86
static HeapTuple tts_virtual_copy_heap_tuple(TupleTableSlot *slot)
Definition: execTuples.c:268
static void tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
Definition: execTuples.c:487
static MinimalTuple tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot)
Definition: execTuples.c:810
#define Min(x, y)
Definition: c.h:890
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
Definition: execTuples.c:2251
static void tts_minimal_init(TupleTableSlot *slot)
Definition: execTuples.c:452
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define TTS_FLAG_SHOULDFREE
Definition: tuptable.h:100
#define InvalidBuffer
Definition: buf.h:25
#define TTS_IS_MINIMALTUPLE(slot)
Definition: tuptable.h:230
Definition: nodes.h:524
#define strVal(v)
Definition: value.h:54
const TupleTableSlotOps *const tts_ops
Definition: tuptable.h:122
HeapTuple tuple
Definition: tuptable.h:250
#define MemSet(start, val, len)
Definition: c.h:941
void(* release)(TupleTableSlot *slot)
Definition: tuptable.h:144
MemoryContext tts_mcxt
Definition: tuptable.h:129
Datum * tts_values
Definition: tuptable.h:126
int32 * atttypmods
Definition: funcapi.h:48
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1283
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3353
TupleTableSlot * slot
Definition: executor.h:457
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
EState * state
Definition: execnodes.h:947
struct VirtualTupleTableSlot VirtualTupleTableSlot
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
static void tts_heap_clear(TupleTableSlot *slot)
Definition: execTuples.c:304
char * resname
Definition: primnodes.h:1395
int namestrcpy(Name name, const char *str)
Definition: name.c:250
static Datum tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: execTuples.c:333
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:289
MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1439
Oid * attioparams
Definition: funcapi.h:45
static HeapTuple tts_minimal_copy_heap_tuple(TupleTableSlot *slot)
Definition: execTuples.c:575
static MinimalTuple tts_minimal_get_minimal_tuple(TupleTableSlot *slot)
Definition: execTuples.c:564
#define fetchatt(A, T)
Definition: tupmacs.h:39
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1433
const TupleTableSlotOps * resultops
Definition: execnodes.h:1020
signed int int32
Definition: c.h:346
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2111
void assign_record_type_typmod(TupleDesc tupDesc)
Definition: typcache.c:1772
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:468
static pg_attribute_always_inline void slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts)
Definition: execTuples.c:889
NodeTag type
Definition: tuptable.h:117
PlanState ps
Definition: execnodes.h:1280
uint16 tts_flags
Definition: tuptable.h:119
static Datum tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: execTuples.c:680
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:983
static HeapTuple tts_heap_get_heap_tuple(TupleTableSlot *slot)
Definition: execTuples.c:395
void pfree(void *pointer)
Definition: mcxt.c:1031
static void tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
Definition: execTuples.c:130
bool resjunk
Definition: primnodes.h:1400
void end_tup_output(TupOutputState *tstate)
Definition: execTuples.c:2309
struct HeapTupleTableSlot HeapTupleTableSlot
#define ERROR
Definition: elog.h:43
Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: heaptuple.c:627
void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1476
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1427
#define HeapTupleHeaderGetNatts(tup)
Definition: htup_details.h:531
HeapTuple(* get_heap_tuple)(TupleTableSlot *slot)
Definition: tuptable.h:188
int32 tdtypmod
Definition: tupdesc.h:83
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
static void tts_virtual_init(TupleTableSlot *slot)
Definition: execTuples.c:97
ItemPointerData t_ctid
Definition: htup_details.h:160
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2231
ItemPointerData t_self
Definition: htup.h:65
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition: tupdesc.c:769
static void slot_getallattrs(TupleTableSlot *slot)
Definition: tuptable.h:355
void(* init)(TupleTableSlot *slot)
Definition: tuptable.h:141
#define lfirst_node(type, lc)
Definition: pg_list.h:193
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2047
uint32 t_len
Definition: htup.h:64
#define HeapTupleHasNulls(tuple)
Definition: htup_details.h:661
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1775
static HeapTuple tts_buffer_heap_copy_heap_tuple(TupleTableSlot *slot)
Definition: execTuples.c:797
const TupleTableSlotOps * scanops
Definition: execnodes.h:1017
static MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot)
Definition: tuptable.h:464
static Datum tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: execTuples.c:136
Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)
Definition: tuptoaster.c:1182
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
bool * tts_isnull
Definition: tuptable.h:128
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1218
TupleConstr * constr
Definition: tupdesc.h:85
static MinimalTuple tts_minimal_copy_minimal_tuple(TupleTableSlot *slot)
Definition: execTuples.c:586
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1719
static void tts_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: execTuples.c:382
TupleDesc tupdesc
Definition: funcapi.h:39
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
static void tts_buffer_heap_init(TupleTableSlot *slot)
Definition: execTuples.c:628
unsigned int uint32
Definition: c.h:358
Oid t_tableOid
Definition: htup.h:66
MinimalTuple(* get_minimal_tuple)(TupleTableSlot *slot)
Definition: tuptable.h:196
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
Definition: expandeddatum.c:75
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
#define init()
static Datum tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition: execTuples.c:497
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:174
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2641
bool resultopsset
Definition: execnodes.h:1028
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
Definition: execTuples.c:1608
TupleTableSlot * ExecAllocTableSlot(List **tupleTable, TupleDesc desc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1135
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:984
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
Definition: execTuples.c:1570
static void tts_minimal_store_tuple(TupleTableSlot *slot, MinimalTuple mtup, bool shouldFree)
Definition: execTuples.c:597
struct BufferHeapTupleTableSlot BufferHeapTupleTableSlot
List * lappend(List *list, void *datum)
Definition: list.c:321
int ExecCleanTargetListLength(List *targetlist)
Definition: execUtils.c:1100
MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1356
static void tts_heap_release(TupleTableSlot *slot)
Definition: execTuples.c:299
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
TupleDesc ps_ResultTupleDesc
Definition: execnodes.h:982
HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)
Definition: heaptuple.c:1458
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
uint8 bits8
Definition: c.h:365
List * es_tupleTable
Definition: execnodes.h:552
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
Definition: execTuples.c:2279
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1155
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
static void tts_minimal_release(TupleTableSlot *slot)
Definition: execTuples.c:464
#define TTS_IS_BUFFERTUPLE(slot)
Definition: tuptable.h:231
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:1253
TupleDesc scandesc
Definition: execnodes.h:992
static void tts_virtual_materialize(TupleTableSlot *slot)
Definition: execTuples.c:151
static MinimalTuple tts_heap_copy_minimal_tuple(TupleTableSlot *slot)
Definition: execTuples.c:419
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2062
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Definition: expandeddatum.c:81
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:124
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:458
TupleTableSlot * ExecStoreBufferHeapTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer)
Definition: execTuples.c:1356
static void tts_buffer_heap_clear(TupleTableSlot *slot)
Definition: execTuples.c:638
#define HeapTupleHeaderHasExternal(tup)
Definition: htup_details.h:539
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1076
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:444
static MinimalTuple tts_virtual_copy_minimal_tuple(TupleTableSlot *slot)
Definition: execTuples.c:279
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1531
Plan * plan
Definition: execnodes.h:945
int16 attnum
Definition: pg_attribute.h:79
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
Definition: tuptable.h:453
struct MinimalTupleTableSlot MinimalTupleTableSlot
MinimalTuple(* copy_minimal_tuple)(TupleTableSlot *slot)
Definition: tuptable.h:216
static void tts_buffer_heap_getsomeattrs(TupleTableSlot *slot, int natts)
Definition: execTuples.c:670
bool scanopsfixed
Definition: execnodes.h:1021
static void tts_minimal_clear(TupleTableSlot *slot)
Definition: execTuples.c:469
#define TTS_IS_HEAPTUPLE(slot)
Definition: tuptable.h:229
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
static void tts_heap_init(TupleTableSlot *slot)
Definition: execTuples.c:294
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1811
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1743
static void tts_minimal_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: execTuples.c:551
Expr * expr
Definition: primnodes.h:1393
#define TTS_FLAG_FIXED
Definition: tuptable.h:108
size_t Size
Definition: c.h:466
static void tts_virtual_clear(TupleTableSlot *slot)
Definition: execTuples.c:107
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:169
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
TupleDesc ExecTypeFromTL(List *targetList)
Definition: execTuples.c:1903
#define MAXALIGN(LEN)
Definition: c.h:685
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1763
void(* getsomeattrs)(TupleTableSlot *slot, int natts)
Definition: tuptable.h:161
bool scanopsset
Definition: execnodes.h:1025
static void tts_heap_getsomeattrs(TupleTableSlot *slot, int natts)
Definition: execTuples.c:323
#define MINIMAL_TUPLE_OFFSET
Definition: htup_details.h:619
TupleTableSlot * ExecStorePinnedBufferHeapTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer)
Definition: execTuples.c:1382
void(* materialize)(TupleTableSlot *slot)
Definition: tuptable.h:174
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
List * targetlist
Definition: plannodes.h:140
#define DatumGetPointer(X)
Definition: postgres.h:549
static void tts_buffer_heap_materialize(TupleTableSlot *slot)
Definition: execTuples.c:689
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:116
struct AttrMissing * missing
Definition: tupdesc.h:41
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1249
static Datum values[MAXATTR]
Definition: bootstrap.c:167
bool resultopsfixed
Definition: execnodes.h:1024
Oid tdtypeid
Definition: tupdesc.h:82
MinimalTuple mintuple
Definition: tuptable.h:284
#define TTS_SLOW(slot)
Definition: tuptable.h:105
e
Definition: preproc-init.c:82
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:162
MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup)
Definition: heaptuple.c:1480
Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
Definition: execTuples.c:2200
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:1962
void * palloc(Size size)
Definition: mcxt.c:924
static void tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: execTuples.c:244
void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
Definition: execTuples.c:1832
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
static HeapTuple tts_heap_copy_heap_tuple(TupleTableSlot *slot)
Definition: execTuples.c:407
void list_free(List *list)
Definition: list.c:1330
#define elog(elevel,...)
Definition: elog.h:226
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
#define NameStr(name)
Definition: c.h:609
HeapTupleData minhdr
Definition: tuptable.h:285
static void tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
Definition: execTuples.c:430
#define pg_attribute_always_inline
Definition: c.h:164
void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum)
Definition: execTuples.c:1867
#define unlikely(x)
Definition: c.h:208
FmgrInfo * attinfuncs
Definition: funcapi.h:42
AttrNumber tts_nvalid
Definition: tuptable.h:121
HeapTupleTableSlot base
Definition: tuptable.h:259
DestReceiver * dest
Definition: executor.h:458
static void tts_buffer_heap_release(TupleTableSlot *slot)
Definition: execTuples.c:633
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
HeapTupleData tupdata
Definition: tuptable.h:253
Definition: pg_list.h:50
ItemPointerData tts_tid
Definition: tuptable.h:130
int Buffer
Definition: buf.h:23
Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
Definition: execTuples.c:1687
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
Definition: execTuples.c:2001
long val
Definition: informix.c:689
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
void IncrBufferRefCount(Buffer buffer)
Definition: bufmgr.c:3391
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1316
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1516
#define TTS_FLAG_SLOW
Definition: tuptable.h:104
static void tts_virtual_release(TupleTableSlot *slot)
Definition: execTuples.c:102
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:452
size_t base_slot_size
Definition: tuptable.h:138