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