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