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