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