PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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"
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
73static TupleDesc ExecTypeFromTLInternal(List *targetList,
74 bool skipjunk);
76 int reqnatts, bool support_cstring);
77static inline void tts_buffer_heap_store_tuple(TupleTableSlot *slot,
78 HeapTuple tuple,
79 Buffer buffer,
80 bool transfer_pin);
81static 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 */
97static void
101
102static void
106
107static void
109{
110 if (unlikely(TTS_SHOULDFREE(slot)))
111 {
113
114 pfree(vslot->data);
115 vslot->data = NULL;
116
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 */
129static 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 */
140static Datum
142{
143 Assert(!TTS_EMPTY(slot));
144
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 */
156static bool
158{
159 Assert(!TTS_EMPTY(slot));
160
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 */
175static 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 {
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 */
207 }
208 else
209 {
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 {
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_nominal_alignby(data,
246 att->attalignby);
247 data_length = EOH_get_flat_size(eoh);
248 EOH_flatten_into(eoh, data, data_length);
249
251 data += data_length;
252 }
253 else
254 {
255 Size data_length = 0;
256
257 data = (char *) att_nominal_alignby(data, att->attalignby);
258 data_length = att_addlength_datum(data_length, att->attlen, val);
259
260 memcpy(data, DatumGetPointer(val), data_length);
261
263 data += data_length;
264 }
265 }
266}
267
268static void
270{
271 TupleDesc srcdesc = srcslot->tts_tupleDescriptor;
272
273 tts_virtual_clear(dstslot);
274
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 */
288}
289
290static HeapTuple
292{
293 Assert(!TTS_EMPTY(slot));
294
296 slot->tts_values,
297 slot->tts_isnull);
298}
299
300static MinimalTuple
302{
303 Assert(!TTS_EMPTY(slot));
304
306 slot->tts_values,
307 slot->tts_isnull,
308 extra);
309}
310
311
312/*
313 * TupleTableSlotOps implementation for HeapTupleTableSlot.
314 */
315
316static void
320
321static void
325
326static void
328{
330
331 /* Free the memory for the heap tuple if it's allowed. */
332 if (TTS_SHOULDFREE(slot))
333 {
334 heap_freetuple(hslot->tuple);
336 }
337
338 slot->tts_nvalid = 0;
339 slot->tts_flags |= TTS_FLAG_EMPTY;
341 hslot->off = 0;
342 hslot->tuple = NULL;
343}
344
345static void
347{
349
350 Assert(!TTS_EMPTY(slot));
351
352 slot_deform_heap_tuple(slot, hslot->tuple, &hslot->off, natts, false);
353}
354
355static Datum
357{
359
360 Assert(!TTS_EMPTY(slot));
361
362 /*
363 * In some code paths it's possible to get here with a non-materialized
364 * slot, in which case we can't retrieve system columns.
365 */
366 if (!hslot->tuple)
369 errmsg("cannot retrieve a system column in this context")));
370
371 return heap_getsysattr(hslot->tuple, attnum,
372 slot->tts_tupleDescriptor, isnull);
373}
374
375static bool
377{
379 TransactionId xmin;
380
381 Assert(!TTS_EMPTY(slot));
382
383 /*
384 * In some code paths it's possible to get here with a non-materialized
385 * slot, in which case we can't check if tuple is created by the current
386 * transaction.
387 */
388 if (!hslot->tuple)
391 errmsg("don't have a storage tuple in this context")));
392
393 xmin = HeapTupleHeaderGetRawXmin(hslot->tuple->t_data);
394
396}
397
398static void
400{
403
404 Assert(!TTS_EMPTY(slot));
405
406 /* If slot has its tuple already materialized, nothing to do. */
407 if (TTS_SHOULDFREE(slot))
408 return;
409
411
412 /*
413 * Have to deform from scratch, otherwise tts_values[] entries could point
414 * into the non-materialized tuple (which might be gone when accessed).
415 */
416 slot->tts_nvalid = 0;
417 hslot->off = 0;
418
419 if (!hslot->tuple)
421 slot->tts_values,
422 slot->tts_isnull);
423 else
424 {
425 /*
426 * The tuple contained in this slot is not allocated in the memory
427 * context of the given slot (else it would have TTS_FLAG_SHOULDFREE
428 * set). Copy the tuple into the given slot's memory context.
429 */
430 hslot->tuple = heap_copytuple(hslot->tuple);
431 }
432
434
436}
437
438static void
440{
441 HeapTuple tuple;
442 MemoryContext oldcontext;
443
444 oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
446 MemoryContextSwitchTo(oldcontext);
447
448 ExecStoreHeapTuple(tuple, dstslot, true);
449}
450
451static HeapTuple
453{
455
456 Assert(!TTS_EMPTY(slot));
457 if (!hslot->tuple)
459
460 return hslot->tuple;
461}
462
463static HeapTuple
465{
467
468 Assert(!TTS_EMPTY(slot));
469 if (!hslot->tuple)
471
472 return heap_copytuple(hslot->tuple);
473}
474
475static MinimalTuple
477{
479
480 if (!hslot->tuple)
482
483 return minimal_tuple_from_heap_tuple(hslot->tuple, extra);
484}
485
486static void
488{
490
491 tts_heap_clear(slot);
492
493 slot->tts_nvalid = 0;
494 hslot->tuple = tuple;
495 hslot->off = 0;
497 slot->tts_tid = tuple->t_self;
498
499 if (shouldFree)
501}
502
503
504/*
505 * TupleTableSlotOps implementation for MinimalTupleTableSlot.
506 */
507
508static void
510{
512
513 /*
514 * Initialize the heap tuple pointer to access attributes of the minimal
515 * tuple contained in the slot as if it's a heap tuple.
516 */
517 mslot->tuple = &mslot->minhdr;
518}
519
520static void
524
525static void
527{
529
530 if (TTS_SHOULDFREE(slot))
531 {
534 }
535
536 slot->tts_nvalid = 0;
537 slot->tts_flags |= TTS_FLAG_EMPTY;
539 mslot->off = 0;
540 mslot->mintuple = NULL;
541}
542
543static void
545{
547
548 Assert(!TTS_EMPTY(slot));
549
550 slot_deform_heap_tuple(slot, mslot->tuple, &mslot->off, natts, true);
551}
552
553/*
554 * MinimalTupleTableSlots never provide system attributes. We generally
555 * shouldn't get here, but provide a user-friendly message if we do.
556 */
557static Datum
559{
560 Assert(!TTS_EMPTY(slot));
561
564 errmsg("cannot retrieve a system column in this context")));
565
566 return 0; /* silence compiler warnings */
567}
568
569/*
570 * Within MinimalTuple abstraction transaction information is unavailable.
571 * We generally shouldn't get here, but provide a user-friendly message if
572 * we do.
573 */
574static bool
576{
577 Assert(!TTS_EMPTY(slot));
578
581 errmsg("don't have transaction information for this type of tuple")));
582
583 return false; /* silence compiler warnings */
584}
585
586static void
588{
591
592 Assert(!TTS_EMPTY(slot));
593
594 /* If slot has its tuple already materialized, nothing to do. */
595 if (TTS_SHOULDFREE(slot))
596 return;
597
599
600 /*
601 * Have to deform from scratch, otherwise tts_values[] entries could point
602 * into the non-materialized tuple (which might be gone when accessed).
603 */
604 slot->tts_nvalid = 0;
605 mslot->off = 0;
606
607 if (!mslot->mintuple)
608 {
610 slot->tts_values,
611 slot->tts_isnull,
612 0);
613 }
614 else
615 {
616 /*
617 * The minimal tuple contained in this slot is not allocated in the
618 * memory context of the given slot (else it would have
619 * TTS_FLAG_SHOULDFREE set). Copy the minimal tuple into the given
620 * slot's memory context.
621 */
622 mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple, 0);
623 }
624
626
627 Assert(mslot->tuple == &mslot->minhdr);
628
629 mslot->minhdr.t_len = mslot->mintuple->t_len + MINIMAL_TUPLE_OFFSET;
630 mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mslot->mintuple - MINIMAL_TUPLE_OFFSET);
631
633}
634
635static void
637{
638 MemoryContext oldcontext;
639 MinimalTuple mintuple;
640
641 oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
643 MemoryContextSwitchTo(oldcontext);
644
645 ExecStoreMinimalTuple(mintuple, dstslot, true);
646}
647
648static MinimalTuple
650{
652
653 if (!mslot->mintuple)
655
656 return mslot->mintuple;
657}
658
659static HeapTuple
661{
663
664 if (!mslot->mintuple)
666
667 return heap_tuple_from_minimal_tuple(mslot->mintuple);
668}
669
670static MinimalTuple
672{
674
675 if (!mslot->mintuple)
677
678 return heap_copy_minimal_tuple(mslot->mintuple, extra);
679}
680
681static void
683{
685
686 tts_minimal_clear(slot);
687
688 Assert(!TTS_SHOULDFREE(slot));
689 Assert(TTS_EMPTY(slot));
690
691 slot->tts_flags &= ~TTS_FLAG_EMPTY;
692 slot->tts_nvalid = 0;
693 mslot->off = 0;
694
695 mslot->mintuple = mtup;
696 Assert(mslot->tuple == &mslot->minhdr);
697 mslot->minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
698 mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
699 /* no need to set t_self or t_tableOid since we won't allow access */
700
701 if (shouldFree)
703}
704
705
706/*
707 * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
708 */
709
710static void
714
715static void
719
720static void
722{
724
725 /*
726 * Free the memory for heap tuple if allowed. A tuple coming from buffer
727 * can never be freed. But we may have materialized a tuple from buffer.
728 * Such a tuple can be freed.
729 */
730 if (TTS_SHOULDFREE(slot))
731 {
732 /* We should have unpinned the buffer while materializing the tuple. */
733 Assert(!BufferIsValid(bslot->buffer));
734
735 heap_freetuple(bslot->base.tuple);
737 }
738
739 if (BufferIsValid(bslot->buffer))
740 ReleaseBuffer(bslot->buffer);
741
742 slot->tts_nvalid = 0;
743 slot->tts_flags |= TTS_FLAG_EMPTY;
745 bslot->base.tuple = NULL;
746 bslot->base.off = 0;
747 bslot->buffer = InvalidBuffer;
748}
749
750static void
752{
754
755 Assert(!TTS_EMPTY(slot));
756
757 slot_deform_heap_tuple(slot, bslot->base.tuple, &bslot->base.off, natts, false);
758}
759
760static Datum
762{
764
765 Assert(!TTS_EMPTY(slot));
766
767 /*
768 * In some code paths it's possible to get here with a non-materialized
769 * slot, in which case we can't retrieve system columns.
770 */
771 if (!bslot->base.tuple)
774 errmsg("cannot retrieve a system column in this context")));
775
776 return heap_getsysattr(bslot->base.tuple, attnum,
777 slot->tts_tupleDescriptor, isnull);
778}
779
780static bool
782{
784 TransactionId xmin;
785
786 Assert(!TTS_EMPTY(slot));
787
788 /*
789 * In some code paths it's possible to get here with a non-materialized
790 * slot, in which case we can't check if tuple is created by the current
791 * transaction.
792 */
793 if (!bslot->base.tuple)
796 errmsg("don't have a storage tuple in this context")));
797
798 xmin = HeapTupleHeaderGetRawXmin(bslot->base.tuple->t_data);
799
801}
802
803static void
805{
808
809 Assert(!TTS_EMPTY(slot));
810
811 /* If slot has its tuple already materialized, nothing to do. */
812 if (TTS_SHOULDFREE(slot))
813 return;
814
816
817 /*
818 * Have to deform from scratch, otherwise tts_values[] entries could point
819 * into the non-materialized tuple (which might be gone when accessed).
820 */
821 bslot->base.off = 0;
822 slot->tts_nvalid = 0;
823
824 if (!bslot->base.tuple)
825 {
826 /*
827 * Normally BufferHeapTupleTableSlot should have a tuple + buffer
828 * associated with it, unless it's materialized (which would've
829 * returned above). But when it's useful to allow storing virtual
830 * tuples in a buffer slot, which then also needs to be
831 * materializable.
832 */
833 bslot->base.tuple = heap_form_tuple(slot->tts_tupleDescriptor,
834 slot->tts_values,
835 slot->tts_isnull);
836 }
837 else
838 {
839 bslot->base.tuple = heap_copytuple(bslot->base.tuple);
840
841 /*
842 * A heap tuple stored in a BufferHeapTupleTableSlot should have a
843 * buffer associated with it, unless it's materialized or virtual.
844 */
845 if (likely(BufferIsValid(bslot->buffer)))
846 ReleaseBuffer(bslot->buffer);
847 bslot->buffer = InvalidBuffer;
848 }
849
850 /*
851 * We don't set TTS_FLAG_SHOULDFREE until after releasing the buffer, if
852 * any. This avoids having a transient state that would fall foul of our
853 * assertions that a slot with TTS_FLAG_SHOULDFREE doesn't own a buffer.
854 * In the unlikely event that ReleaseBuffer() above errors out, we'd
855 * effectively leak the copied tuple, but that seems fairly harmless.
856 */
858
860}
861
862static void
864{
867
868 /*
869 * If the source slot is of a different kind, or is a buffer slot that has
870 * been materialized / is virtual, make a new copy of the tuple. Otherwise
871 * make a new reference to the in-buffer tuple.
872 */
873 if (dstslot->tts_ops != srcslot->tts_ops ||
875 !bsrcslot->base.tuple)
876 {
878
879 ExecClearTuple(dstslot);
880 dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
883 dstslot->tts_flags |= TTS_FLAG_SHOULDFREE;
885 }
886 else
887 {
888 Assert(BufferIsValid(bsrcslot->buffer));
889
890 tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple,
891 bsrcslot->buffer, false);
892
893 /*
894 * The HeapTupleData portion of the source tuple might be shorter
895 * lived than the destination slot. Therefore copy the HeapTuple into
896 * our slot's tupdata, which is guaranteed to live long enough (but
897 * will still point into the buffer).
898 */
899 memcpy(&bdstslot->base.tupdata, bdstslot->base.tuple, sizeof(HeapTupleData));
900 bdstslot->base.tuple = &bdstslot->base.tupdata;
901 }
902}
903
904static HeapTuple
906{
908
909 Assert(!TTS_EMPTY(slot));
910
911 if (!bslot->base.tuple)
913
914 return bslot->base.tuple;
915}
916
917static HeapTuple
919{
921
922 Assert(!TTS_EMPTY(slot));
923
924 if (!bslot->base.tuple)
926
927 return heap_copytuple(bslot->base.tuple);
928}
929
930static MinimalTuple
932{
934
935 Assert(!TTS_EMPTY(slot));
936
937 if (!bslot->base.tuple)
939
940 return minimal_tuple_from_heap_tuple(bslot->base.tuple, extra);
941}
942
943static inline void
945 Buffer buffer, bool transfer_pin)
946{
948
949 if (TTS_SHOULDFREE(slot))
950 {
951 /* materialized slot shouldn't have a buffer to release */
952 Assert(!BufferIsValid(bslot->buffer));
953
954 heap_freetuple(bslot->base.tuple);
956 }
957
958 slot->tts_flags &= ~TTS_FLAG_EMPTY;
959 slot->tts_nvalid = 0;
960 bslot->base.tuple = tuple;
961 bslot->base.off = 0;
962 slot->tts_tid = tuple->t_self;
963
964 /*
965 * If tuple is on a disk page, keep the page pinned as long as we hold a
966 * pointer into it. We assume the caller already has such a pin. If
967 * transfer_pin is true, we'll transfer that pin to this slot, if not
968 * we'll pin it again ourselves.
969 *
970 * This is coded to optimize the case where the slot previously held a
971 * tuple on the same disk page: in that case releasing and re-acquiring
972 * the pin is a waste of cycles. This is a common situation during
973 * seqscans, so it's worth troubling over.
974 */
975 if (bslot->buffer != buffer)
976 {
977 if (BufferIsValid(bslot->buffer))
978 ReleaseBuffer(bslot->buffer);
979
980 bslot->buffer = buffer;
981
982 if (!transfer_pin && BufferIsValid(buffer))
983 IncrBufferRefCount(buffer);
984 }
985 else if (transfer_pin && BufferIsValid(buffer))
986 {
987 /*
988 * In transfer_pin mode the caller won't know about the same-page
989 * optimization, so we gotta release its pin.
990 */
991 ReleaseBuffer(buffer);
992 }
993}
994
995/*
996 * slot_deform_heap_tuple
997 * Given a TupleTableSlot, extract data from the slot's physical tuple
998 * into its Datum/isnull arrays. Data is extracted up through the
999 * reqnatts'th column. If there are insufficient attributes in the given
1000 * tuple, then slot_getmissingattrs() is called to populate the
1001 * remainder. If reqnatts is above the number of attributes in the
1002 * slot's TupleDesc, an error is raised.
1003 *
1004 * This is essentially an incremental version of heap_deform_tuple:
1005 * on each call we extract attributes up to the one needed, without
1006 * re-computing information about previously extracted attributes.
1007 * slot->tts_nvalid is the number of attributes already extracted.
1008 *
1009 * This is marked as always inline, so the different offp for different types
1010 * of slots gets optimized away.
1011 *
1012 * support_cstring should be passed as a const to allow the compiler only
1013 * emit code during inlining for cstring deforming when it's required.
1014 * cstrings can exist in MinimalTuples, but not in HeapTuples.
1015 */
1018 int reqnatts, bool support_cstring)
1019{
1023 HeapTupleHeader tup = tuple->t_data;
1024 size_t attnum;
1026 int firstNonGuaranteedAttr;
1027 int firstNullAttr;
1028 int natts;
1029 Datum *values;
1030 bool *isnull;
1031 char *tp; /* ptr to tuple data */
1032 uint32 off; /* offset in tuple data */
1033
1034 /* Did someone forget to call TupleDescFinalize()? */
1035 Assert(tupleDesc->firstNonCachedOffsetAttr >= 0);
1036
1037 isnull = slot->tts_isnull;
1038
1039 /*
1040 * Some callers may form and deform tuples prior to NOT NULL constraints
1041 * being checked. Here we'd like to optimize the case where we only need
1042 * to fetch attributes before or up to the point where the attribute is
1043 * guaranteed to exist in the tuple. We rely on the slot flag being set
1044 * correctly to only enable this optimization when it's valid to do so.
1045 * This optimization allows us to save fetching the number of attributes
1046 * from the tuple and saves the additional cost of handling non-byval
1047 * attrs.
1048 */
1049 firstNonGuaranteedAttr = Min(reqnatts, slot->tts_first_nonguaranteed);
1050
1051 firstNonCacheOffsetAttr = tupleDesc->firstNonCachedOffsetAttr;
1052
1053 if (HeapTupleHasNulls(tuple))
1054 {
1056 tp = (char *) tup + MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) +
1057 BITMAPLEN(natts));
1058
1059 natts = Min(natts, reqnatts);
1060 if (natts > firstNonGuaranteedAttr)
1061 {
1062 uint8 *bp = tup->t_bits;
1063
1064 /* Find the first NULL attr */
1066
1067 /*
1068 * And populate the isnull array for all attributes being fetched
1069 * from the tuple.
1070 */
1071 populate_isnull_array(bp, natts, isnull);
1072 }
1073 else
1074 {
1075 /* Otherwise all required columns are guaranteed to exist */
1076 firstNullAttr = natts;
1077
1078 /*
1079 * Check TupleDescFinalize() didn't get confused when setting
1080 * firstNonGuaranteedAttr. There should never be a NULL in a
1081 * guaranteed column.
1082 */
1083 Assert(first_null_attr(tup->t_bits, natts) >= firstNullAttr);
1084 }
1085 }
1086 else
1087 {
1088 tp = (char *) tup + MAXALIGN(offsetof(HeapTupleHeaderData, t_bits));
1089
1090 /*
1091 * We only need to look at the tuple's natts if we need more than the
1092 * guaranteed number of columns
1093 */
1094 if (reqnatts > firstNonGuaranteedAttr)
1096 else
1097 {
1098 /* No need to access the number of attributes in the tuple */
1099 natts = reqnatts;
1100 }
1101
1102 /* All attrs can be fetched without checking for NULLs */
1103 firstNullAttr = natts;
1104 }
1105
1106 attnum = slot->tts_nvalid;
1107 values = slot->tts_values;
1108 slot->tts_nvalid = reqnatts;
1109
1110 /*
1111 * We store the tupleDesc's CompactAttribute array in 'cattrs' as gcc
1112 * seems to be unwilling to optimize accessing the CompactAttribute
1113 * element efficiently when accessing it via TupleDescCompactAttr().
1114 */
1115 cattrs = tupleDesc->compact_attrs;
1116
1117 /* Ensure we calculated tp correctly */
1118 Assert(tp == (char *) tup + tup->t_hoff);
1119
1120 if (attnum < firstNonGuaranteedAttr)
1121 {
1122 int attlen;
1123
1124 do
1125 {
1126 isnull[attnum] = false;
1127 cattr = &cattrs[attnum];
1128 attlen = cattr->attlen;
1129
1130 /* We don't expect any non-byval types */
1131 pg_assume(attlen > 0);
1132 Assert(cattr->attbyval == true);
1133
1134 off = cattr->attcacheoff;
1135 values[attnum] = fetch_att_noerr(tp + off, true, attlen);
1136 attnum++;
1137 } while (attnum < firstNonGuaranteedAttr);
1138
1139 off += attlen;
1140
1141 if (attnum == reqnatts)
1142 goto done;
1143 }
1144 else
1145 {
1146 /*
1147 * We may be incrementally deforming the tuple, so set 'off' to the
1148 * previously cached value. This may be 0, if the slot has just
1149 * received a new tuple.
1150 */
1151 off = *offp;
1152
1153 /* We expect *offp to be set to 0 when attnum == 0 */
1154 Assert(off == 0 || attnum > 0);
1155 }
1156
1157 /* We can use attcacheoff up until the first NULL */
1159
1160 /*
1161 * Handle the portion of the tuple that we have cached the offset for up
1162 * to the first NULL attribute. The offset is effectively fixed for
1163 * these, so we can use the CompactAttribute's attcacheoff.
1164 */
1166 {
1167 int attlen;
1168
1169 do
1170 {
1171 isnull[attnum] = false;
1172 cattr = &cattrs[attnum];
1173 attlen = cattr->attlen;
1174 off = cattr->attcacheoff;
1175 values[attnum] = fetch_att_noerr(tp + off,
1176 cattr->attbyval,
1177 attlen);
1178 attnum++;
1179 } while (attnum < firstNonCacheOffsetAttr);
1180
1181 /*
1182 * Point the offset after the end of the last attribute with a cached
1183 * offset. We expect the final cached offset attribute to have a
1184 * fixed width, so just add the attlen to the attcacheoff
1185 */
1186 Assert(attlen > 0);
1187 off += attlen;
1188 }
1189
1190 /*
1191 * Handle any portion of the tuple that doesn't have a fixed offset up
1192 * until the first NULL attribute. This loop only differs from the one
1193 * after it by the NULL checks.
1194 */
1195 for (; attnum < firstNullAttr; attnum++)
1196 {
1197 int attlen;
1198
1199 isnull[attnum] = false;
1200 cattr = &cattrs[attnum];
1201 attlen = cattr->attlen;
1202
1203 /*
1204 * Only emit the cstring-related code in align_fetch_then_add() when
1205 * cstring support is needed. We assume support_cstring will be
1206 * passed as a const to allow the compiler to eliminate this branch.
1207 */
1208 if (!support_cstring)
1209 pg_assume(attlen > 0 || attlen == -1);
1210
1211 /* align 'off', fetch the datum, and increment off beyond the datum */
1213 &off,
1214 cattr->attbyval,
1215 attlen,
1216 cattr->attalignby);
1217 }
1218
1219 /*
1220 * Now handle any remaining attributes in the tuple up to the requested
1221 * attnum. This time, include NULL checks as we're now at the first NULL
1222 * attribute.
1223 */
1224 for (; attnum < natts; attnum++)
1225 {
1226 int attlen;
1227
1228 if (isnull[attnum])
1229 {
1230 values[attnum] = (Datum) 0;
1231 continue;
1232 }
1233
1234 cattr = &cattrs[attnum];
1235 attlen = cattr->attlen;
1236
1237 /* As above, only emit cstring code when needed. */
1238 if (!support_cstring)
1239 pg_assume(attlen > 0 || attlen == -1);
1240
1241 /* align 'off', fetch the datum, and increment off beyond the datum */
1243 &off,
1244 cattr->attbyval,
1245 attlen,
1246 cattr->attalignby);
1247 }
1248
1249 /* Fetch any missing attrs and raise an error if reqnatts is invalid */
1250 if (unlikely(attnum < reqnatts))
1251 {
1252 /*
1253 * Cache the offset before calling the function to allow the compiler
1254 * to implement a tail-call optimization
1255 */
1256 *offp = off;
1258 return;
1259 }
1260done:
1261
1262 /* Save current offset for next execution */
1263 *offp = off;
1264}
1265
1269 .release = tts_virtual_release,
1270 .clear = tts_virtual_clear,
1271 .getsomeattrs = tts_virtual_getsomeattrs,
1272 .getsysattr = tts_virtual_getsysattr,
1273 .materialize = tts_virtual_materialize,
1274 .is_current_xact_tuple = tts_virtual_is_current_xact_tuple,
1275 .copyslot = tts_virtual_copyslot,
1276
1277 /*
1278 * A virtual tuple table slot can not "own" a heap tuple or a minimal
1279 * tuple.
1280 */
1281 .get_heap_tuple = NULL,
1282 .get_minimal_tuple = NULL,
1283 .copy_heap_tuple = tts_virtual_copy_heap_tuple,
1284 .copy_minimal_tuple = tts_virtual_copy_minimal_tuple
1285};
1286
1290 .release = tts_heap_release,
1291 .clear = tts_heap_clear,
1292 .getsomeattrs = tts_heap_getsomeattrs,
1293 .getsysattr = tts_heap_getsysattr,
1294 .is_current_xact_tuple = tts_heap_is_current_xact_tuple,
1295 .materialize = tts_heap_materialize,
1296 .copyslot = tts_heap_copyslot,
1297 .get_heap_tuple = tts_heap_get_heap_tuple,
1298
1299 /* A heap tuple table slot can not "own" a minimal tuple. */
1300 .get_minimal_tuple = NULL,
1301 .copy_heap_tuple = tts_heap_copy_heap_tuple,
1302 .copy_minimal_tuple = tts_heap_copy_minimal_tuple
1303};
1304
1308 .release = tts_minimal_release,
1309 .clear = tts_minimal_clear,
1310 .getsomeattrs = tts_minimal_getsomeattrs,
1311 .getsysattr = tts_minimal_getsysattr,
1312 .is_current_xact_tuple = tts_minimal_is_current_xact_tuple,
1313 .materialize = tts_minimal_materialize,
1314 .copyslot = tts_minimal_copyslot,
1315
1316 /* A minimal tuple table slot can not "own" a heap tuple. */
1317 .get_heap_tuple = NULL,
1318 .get_minimal_tuple = tts_minimal_get_minimal_tuple,
1319 .copy_heap_tuple = tts_minimal_copy_heap_tuple,
1320 .copy_minimal_tuple = tts_minimal_copy_minimal_tuple
1321};
1322
1326 .release = tts_buffer_heap_release,
1327 .clear = tts_buffer_heap_clear,
1328 .getsomeattrs = tts_buffer_heap_getsomeattrs,
1329 .getsysattr = tts_buffer_heap_getsysattr,
1330 .is_current_xact_tuple = tts_buffer_is_current_xact_tuple,
1331 .materialize = tts_buffer_heap_materialize,
1332 .copyslot = tts_buffer_heap_copyslot,
1333 .get_heap_tuple = tts_buffer_heap_get_heap_tuple,
1334
1335 /* A buffer heap tuple table slot can not "own" a minimal tuple. */
1336 .get_minimal_tuple = NULL,
1337 .copy_heap_tuple = tts_buffer_heap_copy_heap_tuple,
1338 .copy_minimal_tuple = tts_buffer_heap_copy_minimal_tuple
1339};
1340
1341
1342/* ----------------------------------------------------------------
1343 * tuple table create/delete functions
1344 * ----------------------------------------------------------------
1345 */
1346
1347/* --------------------------------
1348 * MakeTupleTableSlot
1349 *
1350 * Basic routine to make an empty TupleTableSlot of given
1351 * TupleTableSlotType. If tupleDesc is specified the slot's descriptor is
1352 * fixed for its lifetime, gaining some efficiency. If that's
1353 * undesirable, pass NULL. 'flags' allows any of non-TTS_FLAGS_TRANSIENT
1354 * flags to be set in tts_flags.
1355 * --------------------------------
1356 */
1359 const TupleTableSlotOps *tts_ops, uint16 flags)
1360{
1361 Size basesz,
1362 allocsz;
1363 TupleTableSlot *slot;
1364
1365 basesz = tts_ops->base_slot_size;
1366
1367 /* Ensure callers don't have any way to set transient flags permanently */
1368 flags &= ~TTS_FLAGS_TRANSIENT;
1369
1370 /*
1371 * When a fixed descriptor is specified, we can reduce overhead by
1372 * allocating the entire slot in one go.
1373 *
1374 * We round the size of tts_isnull up to the next highest multiple of 8.
1375 * This is needed as populate_isnull_array() operates on 8 elements at a
1376 * time when converting a tuple's NULL bitmap into a boolean array.
1377 */
1378 if (tupleDesc)
1380 MAXALIGN(tupleDesc->natts * sizeof(Datum)) +
1381 TYPEALIGN(8, tupleDesc->natts * sizeof(bool));
1382 else
1383 allocsz = basesz;
1384
1385 slot = palloc0(allocsz);
1386 /* const for optimization purposes, OK to modify at allocation time */
1387 *((const TupleTableSlotOps **) &slot->tts_ops) = tts_ops;
1388 slot->type = T_TupleTableSlot;
1389 slot->tts_flags = TTS_FLAG_EMPTY | flags;
1390 if (tupleDesc != NULL)
1391 slot->tts_flags |= TTS_FLAG_FIXED;
1394 slot->tts_nvalid = 0;
1395
1396 if (tupleDesc != NULL)
1397 {
1398 slot->tts_values = (Datum *)
1399 (((char *) slot)
1400 + MAXALIGN(basesz));
1401
1402 slot->tts_isnull = (bool *)
1403 (((char *) slot)
1404 + MAXALIGN(basesz)
1405 + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
1406
1408
1409 /*
1410 * Precalculate the maximum guaranteed attribute that has to exist in
1411 * every tuple which gets deformed into this slot. When the
1412 * TTS_FLAG_OBEYS_NOT_NULL_CONSTRAINTS flag is enabled, we simply take
1413 * the pre-calculated value from the tupleDesc, otherwise the
1414 * optimization is disabled, and we set the value to 0.
1415 */
1416 if ((flags & TTS_FLAG_OBEYS_NOT_NULL_CONSTRAINTS) != 0)
1417 slot->tts_first_nonguaranteed = tupleDesc->firstNonGuaranteedAttr;
1418 else
1419 slot->tts_first_nonguaranteed = 0;
1420 }
1421
1422 /*
1423 * And allow slot type specific initialization.
1424 */
1425 slot->tts_ops->init(slot);
1426
1427 return slot;
1428}
1429
1430/* --------------------------------
1431 * ExecAllocTableSlot
1432 *
1433 * Create a tuple table slot within a tuple table (which is just a List).
1434 * --------------------------------
1435 */
1438 const TupleTableSlotOps *tts_ops, uint16 flags)
1439{
1440 TupleTableSlot *slot = MakeTupleTableSlot(desc, tts_ops, flags);
1441
1442 *tupleTable = lappend(*tupleTable, slot);
1443
1444 return slot;
1445}
1446
1447/* --------------------------------
1448 * ExecResetTupleTable
1449 *
1450 * This releases any resources (buffer pins, tupdesc refcounts)
1451 * held by the tuple table, and optionally releases the memory
1452 * occupied by the tuple table data structure.
1453 * It is expected that this routine be called by ExecEndPlan().
1454 * --------------------------------
1455 */
1456void
1458 bool shouldFree) /* true if we should free memory */
1459{
1460 ListCell *lc;
1461
1462 foreach(lc, tupleTable)
1463 {
1465
1466 /* Always release resources and reset the slot to empty */
1467 ExecClearTuple(slot);
1468 slot->tts_ops->release(slot);
1469 if (slot->tts_tupleDescriptor)
1470 {
1472 slot->tts_tupleDescriptor = NULL;
1473 }
1474
1475 /* If shouldFree, release memory occupied by the slot itself */
1476 if (shouldFree)
1477 {
1478 if (!TTS_FIXED(slot))
1479 {
1480 if (slot->tts_values)
1481 pfree(slot->tts_values);
1482 if (slot->tts_isnull)
1483 pfree(slot->tts_isnull);
1484 }
1485 pfree(slot);
1486 }
1487 }
1488
1489 /* If shouldFree, release the list structure */
1490 if (shouldFree)
1492}
1493
1494/* --------------------------------
1495 * MakeSingleTupleTableSlot
1496 *
1497 * This is a convenience routine for operations that need a standalone
1498 * TupleTableSlot not gotten from the main executor tuple table. It makes
1499 * a single slot of given TupleTableSlotType and initializes it to use the
1500 * given tuple descriptor.
1501 * --------------------------------
1502 */
1505 const TupleTableSlotOps *tts_ops)
1506{
1507 TupleTableSlot *slot = MakeTupleTableSlot(tupdesc, tts_ops, 0);
1508
1509 return slot;
1510}
1511
1512/* --------------------------------
1513 * ExecDropSingleTupleTableSlot
1514 *
1515 * Release a TupleTableSlot made with MakeSingleTupleTableSlot.
1516 * DON'T use this on a slot that's part of a tuple table list!
1517 * --------------------------------
1518 */
1519void
1521{
1522 /* This should match ExecResetTupleTable's processing of one slot */
1523 Assert(IsA(slot, TupleTableSlot));
1524 ExecClearTuple(slot);
1525 slot->tts_ops->release(slot);
1526 if (slot->tts_tupleDescriptor)
1528 if (!TTS_FIXED(slot))
1529 {
1530 if (slot->tts_values)
1531 pfree(slot->tts_values);
1532 if (slot->tts_isnull)
1533 pfree(slot->tts_isnull);
1534 }
1535 pfree(slot);
1536}
1537
1538
1539/* ----------------------------------------------------------------
1540 * tuple table slot accessor functions
1541 * ----------------------------------------------------------------
1542 */
1543
1544/* --------------------------------
1545 * ExecSetSlotDescriptor
1546 *
1547 * This function is used to set the tuple descriptor associated
1548 * with the slot's tuple. The passed descriptor must have lifespan
1549 * at least equal to the slot's. If it is a reference-counted descriptor
1550 * then the reference count is incremented for as long as the slot holds
1551 * a reference.
1552 * --------------------------------
1553 */
1554void
1555ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
1556 TupleDesc tupdesc) /* new tuple descriptor */
1557{
1558 Assert(!TTS_FIXED(slot));
1559
1560 /* For safety, make sure slot is empty before changing it */
1561 ExecClearTuple(slot);
1562
1563 /*
1564 * Release any old descriptor. Also release old Datum/isnull arrays if
1565 * present (we don't bother to check if they could be re-used).
1566 */
1567 if (slot->tts_tupleDescriptor)
1569
1570 if (slot->tts_values)
1571 pfree(slot->tts_values);
1572 if (slot->tts_isnull)
1573 pfree(slot->tts_isnull);
1574
1575 /*
1576 * Install the new descriptor; if it's refcounted, bump its refcount.
1577 */
1578 slot->tts_tupleDescriptor = tupdesc;
1579 PinTupleDesc(tupdesc);
1580
1581 /*
1582 * Allocate Datum/isnull arrays of the appropriate size. These must have
1583 * the same lifetime as the slot, so allocate in the slot's own context.
1584 */
1585 slot->tts_values = (Datum *)
1586 MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(Datum));
1587
1588 /*
1589 * We round the size of tts_isnull up to the next highest multiple of 8.
1590 * This is needed as populate_isnull_array() operates on 8 elements at a
1591 * time when converting a tuple's NULL bitmap into a boolean array.
1592 */
1593 slot->tts_isnull = (bool *)
1594 MemoryContextAlloc(slot->tts_mcxt, TYPEALIGN(8, tupdesc->natts * sizeof(bool)));
1595}
1596
1597/* --------------------------------
1598 * ExecStoreHeapTuple
1599 *
1600 * This function is used to store an on-the-fly physical tuple into a specified
1601 * slot in the tuple table.
1602 *
1603 * tuple: tuple to store
1604 * slot: TTSOpsHeapTuple type slot to store it in
1605 * shouldFree: true if ExecClearTuple should pfree() the tuple
1606 * when done with it
1607 *
1608 * shouldFree is normally set 'true' for tuples constructed on-the-fly. But it
1609 * can be 'false' when the referenced tuple is held in a tuple table slot
1610 * belonging to a lower-level executor Proc node. In this case the lower-level
1611 * slot retains ownership and responsibility for eventually releasing the
1612 * tuple. When this method is used, we must be certain that the upper-level
1613 * Proc node will lose interest in the tuple sooner than the lower-level one
1614 * does! If you're not certain, copy the lower-level tuple with heap_copytuple
1615 * and let the upper-level table slot assume ownership of the copy!
1616 *
1617 * Return value is just the passed-in slot pointer.
1618 *
1619 * If the target slot is not guaranteed to be TTSOpsHeapTuple type slot, use
1620 * the, more expensive, ExecForceStoreHeapTuple().
1621 * --------------------------------
1622 */
1625 TupleTableSlot *slot,
1626 bool shouldFree)
1627{
1628 /*
1629 * sanity checks
1630 */
1631 Assert(tuple != NULL);
1632 Assert(slot != NULL);
1634
1635 if (unlikely(!TTS_IS_HEAPTUPLE(slot)))
1636 elog(ERROR, "trying to store a heap tuple into wrong type of slot");
1637 tts_heap_store_tuple(slot, tuple, shouldFree);
1638
1639 slot->tts_tableOid = tuple->t_tableOid;
1640
1641 return slot;
1642}
1643
1644/* --------------------------------
1645 * ExecStoreBufferHeapTuple
1646 *
1647 * This function is used to store an on-disk physical tuple from a buffer
1648 * into a specified slot in the tuple table.
1649 *
1650 * tuple: tuple to store
1651 * slot: TTSOpsBufferHeapTuple type slot to store it in
1652 * buffer: disk buffer if tuple is in a disk page, else InvalidBuffer
1653 *
1654 * The tuple table code acquires a pin on the buffer which is held until the
1655 * slot is cleared, so that the tuple won't go away on us.
1656 *
1657 * Return value is just the passed-in slot pointer.
1658 *
1659 * If the target slot is not guaranteed to be TTSOpsBufferHeapTuple type slot,
1660 * use the, more expensive, ExecForceStoreHeapTuple().
1661 * --------------------------------
1662 */
1665 TupleTableSlot *slot,
1666 Buffer buffer)
1667{
1668 /*
1669 * sanity checks
1670 */
1671 Assert(tuple != NULL);
1672 Assert(slot != NULL);
1674 Assert(BufferIsValid(buffer));
1675
1676 if (unlikely(!TTS_IS_BUFFERTUPLE(slot)))
1677 elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
1678 tts_buffer_heap_store_tuple(slot, tuple, buffer, false);
1679
1680 slot->tts_tableOid = tuple->t_tableOid;
1681
1682 return slot;
1683}
1684
1685/*
1686 * Like ExecStoreBufferHeapTuple, but transfer an existing pin from the caller
1687 * to the slot, i.e. the caller doesn't need to, and may not, release the pin.
1688 */
1691 TupleTableSlot *slot,
1692 Buffer buffer)
1693{
1694 /*
1695 * sanity checks
1696 */
1697 Assert(tuple != NULL);
1698 Assert(slot != NULL);
1700 Assert(BufferIsValid(buffer));
1701
1702 if (unlikely(!TTS_IS_BUFFERTUPLE(slot)))
1703 elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
1704 tts_buffer_heap_store_tuple(slot, tuple, buffer, true);
1705
1706 slot->tts_tableOid = tuple->t_tableOid;
1707
1708 return slot;
1709}
1710
1711/*
1712 * Store a minimal tuple into TTSOpsMinimalTuple type slot.
1713 *
1714 * If the target slot is not guaranteed to be TTSOpsMinimalTuple type slot,
1715 * use the, more expensive, ExecForceStoreMinimalTuple().
1716 */
1719 TupleTableSlot *slot,
1720 bool shouldFree)
1721{
1722 /*
1723 * sanity checks
1724 */
1725 Assert(mtup != NULL);
1726 Assert(slot != NULL);
1728
1729 if (unlikely(!TTS_IS_MINIMALTUPLE(slot)))
1730 elog(ERROR, "trying to store a minimal tuple into wrong type of slot");
1732
1733 return slot;
1734}
1735
1736/*
1737 * Store a HeapTuple into any kind of slot, performing conversion if
1738 * necessary.
1739 */
1740void
1742 TupleTableSlot *slot,
1743 bool shouldFree)
1744{
1745 if (TTS_IS_HEAPTUPLE(slot))
1746 {
1747 ExecStoreHeapTuple(tuple, slot, shouldFree);
1748 }
1749 else if (TTS_IS_BUFFERTUPLE(slot))
1750 {
1753
1754 ExecClearTuple(slot);
1755 slot->tts_flags &= ~TTS_FLAG_EMPTY;
1757 bslot->base.tuple = heap_copytuple(tuple);
1760
1761 if (shouldFree)
1762 pfree(tuple);
1763 }
1764 else
1765 {
1766 ExecClearTuple(slot);
1768 slot->tts_values, slot->tts_isnull);
1770
1771 if (shouldFree)
1772 {
1773 ExecMaterializeSlot(slot);
1774 pfree(tuple);
1775 }
1776 }
1777}
1778
1779/*
1780 * Store a MinimalTuple into any kind of slot, performing conversion if
1781 * necessary.
1782 */
1783void
1785 TupleTableSlot *slot,
1786 bool shouldFree)
1787{
1788 if (TTS_IS_MINIMALTUPLE(slot))
1789 {
1791 }
1792 else
1793 {
1794 HeapTupleData htup;
1795
1796 ExecClearTuple(slot);
1797
1798 htup.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
1799 htup.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
1801 slot->tts_values, slot->tts_isnull);
1803
1804 if (shouldFree)
1805 {
1806 ExecMaterializeSlot(slot);
1807 pfree(mtup);
1808 }
1809 }
1810}
1811
1812/* --------------------------------
1813 * ExecStoreVirtualTuple
1814 * Mark a slot as containing a virtual tuple.
1815 *
1816 * The protocol for loading a slot with virtual tuple data is:
1817 * * Call ExecClearTuple to mark the slot empty.
1818 * * Store data into the Datum/isnull arrays.
1819 * * Call ExecStoreVirtualTuple to mark the slot valid.
1820 * This is a bit unclean but it avoids one round of data copying.
1821 * --------------------------------
1822 */
1825{
1826 /*
1827 * sanity checks
1828 */
1829 Assert(slot != NULL);
1831 Assert(TTS_EMPTY(slot));
1832
1833 slot->tts_flags &= ~TTS_FLAG_EMPTY;
1834 slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
1835
1836 return slot;
1837}
1838
1839/* --------------------------------
1840 * ExecStoreAllNullTuple
1841 * Set up the slot to contain a null in every column.
1842 *
1843 * At first glance this might sound just like ExecClearTuple, but it's
1844 * entirely different: the slot ends up full, not empty.
1845 * --------------------------------
1846 */
1849{
1850 /*
1851 * sanity checks
1852 */
1853 Assert(slot != NULL);
1855
1856 /* Clear any old contents */
1857 ExecClearTuple(slot);
1858
1859 /*
1860 * Fill all the columns of the virtual tuple with nulls
1861 */
1862 MemSet(slot->tts_values, 0,
1863 slot->tts_tupleDescriptor->natts * sizeof(Datum));
1864 memset(slot->tts_isnull, true,
1865 slot->tts_tupleDescriptor->natts * sizeof(bool));
1866
1867 return ExecStoreVirtualTuple(slot);
1868}
1869
1870/*
1871 * Store a HeapTuple in datum form, into a slot. That always requires
1872 * deforming it and storing it in virtual form.
1873 *
1874 * Until the slot is materialized, the contents of the slot depend on the
1875 * datum.
1876 */
1877void
1879{
1880 HeapTupleData tuple = {0};
1881 HeapTupleHeader td;
1882
1884
1886 tuple.t_self = td->t_ctid;
1887 tuple.t_data = td;
1888
1889 ExecClearTuple(slot);
1890
1892 slot->tts_values, slot->tts_isnull);
1894}
1895
1896/*
1897 * ExecFetchSlotHeapTuple - fetch HeapTuple representing the slot's content
1898 *
1899 * The returned HeapTuple represents the slot's content as closely as
1900 * possible.
1901 *
1902 * If materialize is true, the contents of the slots will be made independent
1903 * from the underlying storage (i.e. all buffer pins are released, memory is
1904 * allocated in the slot's context).
1905 *
1906 * If shouldFree is not-NULL it'll be set to true if the returned tuple has
1907 * been allocated in the calling memory context, and must be freed by the
1908 * caller (via explicit pfree() or a memory context reset).
1909 *
1910 * NB: If materialize is true, modifications of the returned tuple are
1911 * allowed. But it depends on the type of the slot whether such modifications
1912 * will also affect the slot's contents. While that is not the nicest
1913 * behaviour, all such modifications are in the process of being removed.
1914 */
1916ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
1917{
1918 /*
1919 * sanity checks
1920 */
1921 Assert(slot != NULL);
1922 Assert(!TTS_EMPTY(slot));
1923
1924 /* Materialize the tuple so that the slot "owns" it, if requested. */
1925 if (materialize)
1926 slot->tts_ops->materialize(slot);
1927
1928 if (slot->tts_ops->get_heap_tuple == NULL)
1929 {
1930 if (shouldFree)
1931 *shouldFree = true;
1932 return slot->tts_ops->copy_heap_tuple(slot);
1933 }
1934 else
1935 {
1936 if (shouldFree)
1937 *shouldFree = false;
1938 return slot->tts_ops->get_heap_tuple(slot);
1939 }
1940}
1941
1942/* --------------------------------
1943 * ExecFetchSlotMinimalTuple
1944 * Fetch the slot's minimal physical tuple.
1945 *
1946 * If the given tuple table slot can hold a minimal tuple, indicated by a
1947 * non-NULL get_minimal_tuple callback, the function returns the minimal
1948 * tuple returned by that callback. It assumes that the minimal tuple
1949 * returned by the callback is "owned" by the slot i.e. the slot is
1950 * responsible for freeing the memory consumed by the tuple. Hence it sets
1951 * *shouldFree to false, indicating that the caller should not free the
1952 * memory consumed by the minimal tuple. In this case the returned minimal
1953 * tuple should be considered as read-only.
1954 *
1955 * If that callback is not supported, it calls copy_minimal_tuple callback
1956 * which is expected to return a copy of minimal tuple representing the
1957 * contents of the slot. In this case *shouldFree is set to true,
1958 * indicating the caller that it should free the memory consumed by the
1959 * minimal tuple. In this case the returned minimal tuple may be written
1960 * up.
1961 * --------------------------------
1962 */
1965 bool *shouldFree)
1966{
1967 /*
1968 * sanity checks
1969 */
1970 Assert(slot != NULL);
1971 Assert(!TTS_EMPTY(slot));
1972
1973 if (slot->tts_ops->get_minimal_tuple)
1974 {
1975 if (shouldFree)
1976 *shouldFree = false;
1977 return slot->tts_ops->get_minimal_tuple(slot);
1978 }
1979 else
1980 {
1981 if (shouldFree)
1982 *shouldFree = true;
1983 return slot->tts_ops->copy_minimal_tuple(slot, 0);
1984 }
1985}
1986
1987/* --------------------------------
1988 * ExecFetchSlotHeapTupleDatum
1989 * Fetch the slot's tuple as a composite-type Datum.
1990 *
1991 * The result is always freshly palloc'd in the caller's memory context.
1992 * --------------------------------
1993 */
1994Datum
1996{
1997 HeapTuple tup;
1998 TupleDesc tupdesc;
1999 bool shouldFree;
2000 Datum ret;
2001
2002 /* Fetch slot's contents in regular-physical-tuple form */
2003 tup = ExecFetchSlotHeapTuple(slot, false, &shouldFree);
2004 tupdesc = slot->tts_tupleDescriptor;
2005
2006 /* Convert to Datum form */
2007 ret = heap_copy_tuple_as_datum(tup, tupdesc);
2008
2009 if (shouldFree)
2010 pfree(tup);
2011
2012 return ret;
2013}
2014
2015/* ----------------------------------------------------------------
2016 * convenience initialization routines
2017 * ----------------------------------------------------------------
2018 */
2019
2020/* ----------------
2021 * ExecInitResultTypeTL
2022 *
2023 * Initialize result type, using the plan node's targetlist.
2024 * ----------------
2025 */
2026void
2028{
2029 TupleDesc tupDesc = ExecTypeFromTL(planstate->plan->targetlist);
2030
2031 planstate->ps_ResultTupleDesc = tupDesc;
2032}
2033
2034/* --------------------------------
2035 * ExecInit{Result,Scan,Extra}TupleSlot[TL]
2036 *
2037 * These are convenience routines to initialize the specified slot
2038 * in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
2039 * is used for initializing special-purpose slots.
2040 * --------------------------------
2041 */
2042
2043/* ----------------
2044 * ExecInitResultTupleSlotTL
2045 *
2046 * Initialize result tuple slot, using the tuple descriptor previously
2047 * computed with ExecInitResultTypeTL().
2048 * ----------------
2049 */
2050void
2052{
2053 TupleTableSlot *slot;
2054
2055 slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
2056 planstate->ps_ResultTupleDesc, tts_ops, 0);
2057 planstate->ps_ResultTupleSlot = slot;
2058
2059 planstate->resultopsfixed = planstate->ps_ResultTupleDesc != NULL;
2060 planstate->resultops = tts_ops;
2061 planstate->resultopsset = true;
2062}
2063
2064/* ----------------
2065 * ExecInitResultTupleSlotTL
2066 *
2067 * Initialize result tuple slot, using the plan node's targetlist.
2068 * ----------------
2069 */
2070void
2072 const TupleTableSlotOps *tts_ops)
2073{
2074 ExecInitResultTypeTL(planstate);
2075 ExecInitResultSlot(planstate, tts_ops);
2076}
2077
2078/* ----------------
2079 * ExecInitScanTupleSlot
2080 * ----------------
2081 */
2082void
2084 TupleDesc tupledesc, const TupleTableSlotOps *tts_ops,
2085 uint16 flags)
2086{
2087 scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
2088 tupledesc, tts_ops, flags);
2089 scanstate->ps.scandesc = tupledesc;
2090 scanstate->ps.scanopsfixed = tupledesc != NULL;
2091 scanstate->ps.scanops = tts_ops;
2092 scanstate->ps.scanopsset = true;
2093}
2094
2095/* ----------------
2096 * ExecInitExtraTupleSlot
2097 *
2098 * Return a newly created slot. If tupledesc is non-NULL the slot will have
2099 * that as its fixed tupledesc. Otherwise the caller needs to use
2100 * ExecSetSlotDescriptor() to set the descriptor before use.
2101 * ----------------
2102 */
2105 TupleDesc tupledesc,
2106 const TupleTableSlotOps *tts_ops)
2107{
2108 return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc, tts_ops, 0);
2109}
2110
2111/* ----------------
2112 * ExecInitNullTupleSlot
2113 *
2114 * Build a slot containing an all-nulls tuple of the given type.
2115 * This is used as a substitute for an input tuple when performing an
2116 * outer join.
2117 * ----------------
2118 */
2121 const TupleTableSlotOps *tts_ops)
2122{
2123 TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_ops);
2124
2125 return ExecStoreAllNullTuple(slot);
2126}
2127
2128/* ---------------------------------------------------------------
2129 * Routines for setting/accessing attributes in a slot.
2130 * ---------------------------------------------------------------
2131 */
2132
2133/*
2134 * Fill in missing values for a TupleTableSlot.
2135 *
2136 * This is only exposed because it's needed for JIT compiled tuple
2137 * deforming. That exception aside, there should be no callers outside of this
2138 * file.
2139 */
2140void
2142{
2144
2145 /* Check for invalid attnums */
2147 elog(ERROR, "invalid attribute number %d", lastAttNum);
2148
2149 if (slot->tts_tupleDescriptor->constr)
2151
2152 if (!attrmiss)
2153 {
2154 /* no missing values array at all, so just fill everything in as NULL */
2155 for (int attnum = startAttNum; attnum < lastAttNum; attnum++)
2156 {
2157 slot->tts_values[attnum] = (Datum) 0;
2158 slot->tts_isnull[attnum] = true;
2159 }
2160 }
2161 else
2162 {
2163 /* use attrmiss to set the missing values */
2164 for (int attnum = startAttNum; attnum < lastAttNum; attnum++)
2165 {
2166 slot->tts_values[attnum] = attrmiss[attnum].am_value;
2167 slot->tts_isnull[attnum] = !attrmiss[attnum].am_present;
2168 }
2169 }
2170}
2171
2172/*
2173 * slot_getsomeattrs_int
2174 * external function to call getsomeattrs() for use in JIT
2175 */
2176void
2178{
2179 /* Check for caller errors */
2180 Assert(slot->tts_nvalid < attnum); /* checked in slot_getsomeattrs */
2181 Assert(attnum > 0);
2182
2183 /* Fetch as many attributes as possible from the underlying tuple. */
2184 slot->tts_ops->getsomeattrs(slot, attnum);
2185
2186 /*
2187 * Avoid putting new code here as that would prevent the compiler from
2188 * using the sibling call optimization for the above function.
2189 */
2190}
2191
2192/* ----------------------------------------------------------------
2193 * ExecTypeFromTL
2194 *
2195 * Generate a tuple descriptor for the result tuple of a targetlist.
2196 * (A parse/plan tlist must be passed, not an ExprState tlist.)
2197 * Note that resjunk columns, if any, are included in the result.
2198 *
2199 * Currently there are about 4 different places where we create
2200 * TupleDescriptors. They should all be merged, or perhaps
2201 * be rewritten to call BuildDesc().
2202 * ----------------------------------------------------------------
2203 */
2206{
2207 return ExecTypeFromTLInternal(targetList, false);
2208}
2209
2210/* ----------------------------------------------------------------
2211 * ExecCleanTypeFromTL
2212 *
2213 * Same as above, but resjunk columns are omitted from the result.
2214 * ----------------------------------------------------------------
2215 */
2218{
2219 return ExecTypeFromTLInternal(targetList, true);
2220}
2221
2222static TupleDesc
2224{
2226 ListCell *l;
2227 int len;
2228 int cur_resno = 1;
2229
2230 if (skipjunk)
2231 len = ExecCleanTargetListLength(targetList);
2232 else
2233 len = ExecTargetListLength(targetList);
2235
2236 foreach(l, targetList)
2237 {
2238 TargetEntry *tle = lfirst(l);
2239
2240 if (skipjunk && tle->resjunk)
2241 continue;
2243 cur_resno,
2244 tle->resname,
2245 exprType((Node *) tle->expr),
2246 exprTypmod((Node *) tle->expr),
2247 0);
2249 cur_resno,
2250 exprCollation((Node *) tle->expr));
2251 cur_resno++;
2252 }
2253
2255
2256 return typeInfo;
2257}
2258
2259/*
2260 * ExecTypeFromExprList - build a tuple descriptor from a list of Exprs
2261 *
2262 * This is roughly like ExecTypeFromTL, but we work from bare expressions
2263 * not TargetEntrys. No names are attached to the tupledesc's columns.
2264 */
2267{
2269 ListCell *lc;
2270 int cur_resno = 1;
2271
2273
2274 foreach(lc, exprList)
2275 {
2276 Node *e = lfirst(lc);
2277
2279 cur_resno,
2280 NULL,
2281 exprType(e),
2282 exprTypmod(e),
2283 0);
2285 cur_resno,
2286 exprCollation(e));
2287 cur_resno++;
2288 }
2289
2291
2292 return typeInfo;
2293}
2294
2295/*
2296 * ExecTypeSetColNames - set column names in a RECORD TupleDesc
2297 *
2298 * Column names must be provided as an alias list (list of String nodes).
2299 */
2300void
2302{
2303 int colno = 0;
2304 ListCell *lc;
2305
2306 /* It's only OK to change col names in a not-yet-blessed RECORD type */
2307 Assert(typeInfo->tdtypeid == RECORDOID);
2308 Assert(typeInfo->tdtypmod < 0);
2309
2310 foreach(lc, namesList)
2311 {
2312 char *cname = strVal(lfirst(lc));
2313 Form_pg_attribute attr;
2314
2315 /* Guard against too-long names list (probably can't happen) */
2316 if (colno >= typeInfo->natts)
2317 break;
2318 attr = TupleDescAttr(typeInfo, colno);
2319 colno++;
2320
2321 /*
2322 * Do nothing for empty aliases or dropped columns (these cases
2323 * probably can't arise in RECORD types, either)
2324 */
2325 if (cname[0] == '\0' || attr->attisdropped)
2326 continue;
2327
2328 /* OK, assign the column name */
2329 namestrcpy(&(attr->attname), cname);
2330 }
2331}
2332
2333/*
2334 * BlessTupleDesc - make a completed tuple descriptor useful for SRFs
2335 *
2336 * Rowtype Datums returned by a function must contain valid type information.
2337 * This happens "for free" if the tupdesc came from a relcache entry, but
2338 * not if we have manufactured a tupdesc for a transient RECORD datatype.
2339 * In that case we have to notify typcache.c of the existence of the type.
2340 *
2341 * TupleDescFinalize() must be called on the TupleDesc before calling this
2342 * function.
2343 */
2346{
2347 /* Did someone forget to call TupleDescFinalize()? */
2348 Assert(tupdesc->firstNonCachedOffsetAttr >= 0);
2349
2350 if (tupdesc->tdtypeid == RECORDOID &&
2351 tupdesc->tdtypmod < 0)
2353
2354 return tupdesc; /* just for notational convenience */
2355}
2356
2357/*
2358 * TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the
2359 * supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
2360 * to produce a properly formed tuple.
2361 */
2364{
2365 int natts = tupdesc->natts;
2366 int i;
2367 Oid atttypeid;
2370 Oid *attioparams;
2371 int32 *atttypmods;
2372 AttInMetadata *attinmeta;
2373
2374 attinmeta = palloc_object(AttInMetadata);
2375
2376 /* "Bless" the tupledesc so that we can make rowtype datums with it */
2377 attinmeta->tupdesc = BlessTupleDesc(tupdesc);
2378
2379 /*
2380 * Gather info needed later to call the "in" function for each attribute
2381 */
2382 attinfuncinfo = (FmgrInfo *) palloc0(natts * sizeof(FmgrInfo));
2383 attioparams = (Oid *) palloc0(natts * sizeof(Oid));
2384 atttypmods = (int32 *) palloc0(natts * sizeof(int32));
2385
2386 for (i = 0; i < natts; i++)
2387 {
2388 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2389
2390 /* Ignore dropped attributes */
2391 if (!att->attisdropped)
2392 {
2393 atttypeid = att->atttypid;
2394 getTypeInputInfo(atttypeid, &attinfuncid, &attioparams[i]);
2396 atttypmods[i] = att->atttypmod;
2397 }
2398 }
2399 attinmeta->attinfuncs = attinfuncinfo;
2400 attinmeta->attioparams = attioparams;
2401 attinmeta->atttypmods = atttypmods;
2402
2403 return attinmeta;
2404}
2405
2406/*
2407 * BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
2408 * values is an array of C strings, one for each attribute of the return tuple.
2409 * A NULL string pointer indicates we want to create a NULL field.
2410 */
2413{
2414 TupleDesc tupdesc = attinmeta->tupdesc;
2415 int natts = tupdesc->natts;
2416 Datum *dvalues;
2417 bool *nulls;
2418 int i;
2419 HeapTuple tuple;
2420
2421 dvalues = (Datum *) palloc(natts * sizeof(Datum));
2422 nulls = (bool *) palloc(natts * sizeof(bool));
2423
2424 /*
2425 * Call the "in" function for each non-dropped attribute, even for nulls,
2426 * to support domains.
2427 */
2428 for (i = 0; i < natts; i++)
2429 {
2430 if (!TupleDescCompactAttr(tupdesc, i)->attisdropped)
2431 {
2432 /* Non-dropped attributes */
2433 dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i],
2434 values[i],
2435 attinmeta->attioparams[i],
2436 attinmeta->atttypmods[i]);
2437 if (values[i] != NULL)
2438 nulls[i] = false;
2439 else
2440 nulls[i] = true;
2441 }
2442 else
2443 {
2444 /* Handle dropped attributes by setting to NULL */
2445 dvalues[i] = (Datum) 0;
2446 nulls[i] = true;
2447 }
2448 }
2449
2450 /*
2451 * Form a tuple
2452 */
2453 tuple = heap_form_tuple(tupdesc, dvalues, nulls);
2454
2455 /*
2456 * Release locally palloc'd space. XXX would probably be good to pfree
2457 * values of pass-by-reference datums, as well.
2458 */
2459 pfree(dvalues);
2460 pfree(nulls);
2461
2462 return tuple;
2463}
2464
2465/*
2466 * HeapTupleHeaderGetDatum - convert a HeapTupleHeader pointer to a Datum.
2467 *
2468 * This must *not* get applied to an on-disk tuple; the tuple should be
2469 * freshly made by heap_form_tuple or some wrapper routine for it (such as
2470 * BuildTupleFromCStrings). Be sure also that the tupledesc used to build
2471 * the tuple has a properly "blessed" rowtype.
2472 *
2473 * Formerly this was a macro equivalent to PointerGetDatum, relying on the
2474 * fact that heap_form_tuple fills in the appropriate tuple header fields
2475 * for a composite Datum. However, we now require that composite Datums not
2476 * contain any external TOAST pointers. We do not want heap_form_tuple itself
2477 * to enforce that; more specifically, the rule applies only to actual Datums
2478 * and not to HeapTuple structures. Therefore, HeapTupleHeaderGetDatum is
2479 * now a function that detects whether there are externally-toasted fields
2480 * and constructs a new tuple with inlined fields if so. We still need
2481 * heap_form_tuple to insert the Datum header fields, because otherwise this
2482 * code would have no way to obtain a tupledesc for the tuple.
2483 *
2484 * Note that if we do build a new tuple, it's palloc'd in the current
2485 * memory context. Beware of code that changes context between the initial
2486 * heap_form_tuple/etc call and calling HeapTuple(Header)GetDatum.
2487 *
2488 * For performance-critical callers, it could be worthwhile to take extra
2489 * steps to ensure that there aren't TOAST pointers in the output of
2490 * heap_form_tuple to begin with. It's likely however that the costs of the
2491 * typcache lookup and tuple disassembly/reassembly are swamped by TOAST
2492 * dereference costs, so that the benefits of such extra effort would be
2493 * minimal.
2494 *
2495 * XXX it would likely be better to create wrapper functions that produce
2496 * a composite Datum from the field values in one step. However, there's
2497 * enough code using the existing APIs that we couldn't get rid of this
2498 * hack anytime soon.
2499 */
2500Datum
2502{
2503 Datum result;
2504 TupleDesc tupDesc;
2505
2506 /* No work if there are no external TOAST pointers in the tuple */
2507 if (!HeapTupleHeaderHasExternal(tuple))
2508 return PointerGetDatum(tuple);
2509
2510 /* Use the type data saved by heap_form_tuple to look up the rowtype */
2513
2514 /* And do the flattening */
2517 tupDesc);
2518
2519 ReleaseTupleDesc(tupDesc);
2520
2521 return result;
2522}
2523
2524
2525/*
2526 * Functions for sending tuples to the frontend (or other specified destination)
2527 * as though it is a SELECT result. These are used by utility commands that
2528 * need to project directly to the destination and don't need or want full
2529 * table function capability. Currently used by EXPLAIN and SHOW ALL.
2530 */
2533 TupleDesc tupdesc,
2534 const TupleTableSlotOps *tts_ops)
2535{
2537
2539
2540 tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_ops);
2541 tstate->dest = dest;
2542
2543 tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
2544
2545 return tstate;
2546}
2547
2548/*
2549 * write a single tuple
2550 */
2551void
2552do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
2553{
2554 TupleTableSlot *slot = tstate->slot;
2555 int natts = slot->tts_tupleDescriptor->natts;
2556
2557 /* make sure the slot is clear */
2558 ExecClearTuple(slot);
2559
2560 /* insert data */
2561 memcpy(slot->tts_values, values, natts * sizeof(Datum));
2562 memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
2563
2564 /* mark slot as containing a virtual tuple */
2566
2567 /* send the tuple to the receiver */
2568 (void) tstate->dest->receiveSlot(slot, tstate->dest);
2569
2570 /* clean up */
2571 ExecClearTuple(slot);
2572}
2573
2574/*
2575 * write a chunk of text, breaking at newline characters
2576 *
2577 * Should only be used with a single-TEXT-attribute tupdesc.
2578 */
2579void
2581{
2582 Datum values[1];
2583 bool isnull[1] = {false};
2584
2585 while (*txt)
2586 {
2587 const char *eol;
2588 int len;
2589
2590 eol = strchr(txt, '\n');
2591 if (eol)
2592 {
2593 len = eol - txt;
2594 eol++;
2595 }
2596 else
2597 {
2598 len = strlen(txt);
2599 eol = txt + len;
2600 }
2601
2603 do_tup_output(tstate, values, isnull);
2605 txt = eol;
2606 }
2607}
2608
2609void
2611{
2612 tstate->dest->rShutdown(tstate->dest);
2613 /* note that destroying the dest is not ours to do */
2615 pfree(tstate);
2616}
static Datum values[MAXATTR]
Definition bootstrap.c:190
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
void IncrBufferRefCount(Buffer buffer)
Definition bufmgr.c:5679
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5595
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
#define Min(x, y)
Definition c.h:1091
#define likely(x)
Definition c.h:437
#define MAXALIGN(LEN)
Definition c.h:896
#define TYPEALIGN(ALIGNVAL, LEN)
Definition c.h:889
uint8_t uint8
Definition c.h:622
#define Assert(condition)
Definition c.h:943
#define pg_attribute_always_inline
Definition c.h:305
int32_t int32
Definition c.h:620
uint16_t uint16
Definition c.h:623
#define pg_assume(expr)
Definition c.h:423
#define unlikely(x)
Definition c.h:438
uint32_t uint32
Definition c.h:624
#define MemSet(start, val, len)
Definition c.h:1107
uint32 TransactionId
Definition c.h:736
size_t Size
Definition c.h:689
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
static void tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
Definition execTuples.c:487
static pg_attribute_always_inline void slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int reqnatts, bool support_cstring)
static void tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition execTuples.c:863
static void tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer, bool transfer_pin)
Definition execTuples.c:944
static HeapTuple tts_minimal_copy_heap_tuple(TupleTableSlot *slot)
Definition execTuples.c:660
static MinimalTuple tts_virtual_copy_minimal_tuple(TupleTableSlot *slot, Size extra)
Definition execTuples.c:301
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
static Datum tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition execTuples.c:356
static HeapTuple tts_buffer_heap_copy_heap_tuple(TupleTableSlot *slot)
Definition execTuples.c:918
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
static void tts_buffer_heap_clear(TupleTableSlot *slot)
Definition execTuples.c:721
TupleTableSlot * ExecStorePinnedBufferHeapTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer)
static void tts_minimal_store_tuple(TupleTableSlot *slot, MinimalTuple mtup, bool shouldFree)
Definition execTuples.c:682
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void do_tup_output(TupOutputState *tstate, const Datum *values, const bool *isnull)
const TupleTableSlotOps TTSOpsVirtual
Definition execTuples.c:84
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
static Datum tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition execTuples.c:761
static void tts_minimal_init(TupleTableSlot *slot)
Definition execTuples.c:509
static void tts_heap_init(TupleTableSlot *slot)
Definition execTuples.c:317
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
static bool tts_buffer_is_current_xact_tuple(TupleTableSlot *slot)
Definition execTuples.c:781
Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
static TupleDesc ExecTypeFromTLInternal(List *targetList, bool skipjunk)
static HeapTuple tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
Definition execTuples.c:905
TupleDesc ExecCleanTypeFromTL(List *targetList)
static HeapTuple tts_virtual_copy_heap_tuple(TupleTableSlot *slot)
Definition execTuples.c:291
void ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_ops)
void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList)
void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
const TupleTableSlotOps TTSOpsBufferHeapTuple
Definition execTuples.c:87
static void tts_buffer_heap_release(TupleTableSlot *slot)
Definition execTuples.c:716
void end_tup_output(TupOutputState *tstate)
static void tts_minimal_clear(TupleTableSlot *slot)
Definition execTuples.c:526
static MinimalTuple tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot, Size extra)
Definition execTuples.c:931
MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops, uint16 flags)
void ExecInitResultTypeTL(PlanState *planstate)
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
static void tts_virtual_clear(TupleTableSlot *slot)
Definition execTuples.c:108
static void tts_buffer_heap_materialize(TupleTableSlot *slot)
Definition execTuples.c:804
TupleTableSlot * MakeTupleTableSlot(TupleDesc tupleDesc, const TupleTableSlotOps *tts_ops, uint16 flags)
void do_text_output_multiline(TupOutputState *tstate, const char *txt)
static void tts_virtual_release(TupleTableSlot *slot)
Definition execTuples.c:103
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
static void tts_minimal_materialize(TupleTableSlot *slot)
Definition execTuples.c:587
TupleTableSlot * ExecStoreBufferHeapTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer)
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
static MinimalTuple tts_minimal_get_minimal_tuple(TupleTableSlot *slot)
Definition execTuples.c:649
static void tts_minimal_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition execTuples.c:636
static void tts_virtual_init(TupleTableSlot *slot)
Definition execTuples.c:98
void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot)
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
static void tts_minimal_release(TupleTableSlot *slot)
Definition execTuples.c:521
Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
const TupleTableSlotOps TTSOpsHeapTuple
Definition execTuples.c:85
static HeapTuple tts_heap_copy_heap_tuple(TupleTableSlot *slot)
Definition execTuples.c:464
void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum)
static Datum tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition execTuples.c:558
const TupleTableSlotOps TTSOpsMinimalTuple
Definition execTuples.c:86
static void tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition execTuples.c:269
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
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:751
static void tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
Definition execTuples.c:130
static MinimalTuple tts_heap_copy_minimal_tuple(TupleTableSlot *slot, Size extra)
Definition execTuples.c:476
TupleDesc ExecTypeFromExprList(List *exprList)
static void tts_heap_materialize(TupleTableSlot *slot)
Definition execTuples.c:399
TupleTableSlot * ExecAllocTableSlot(List **tupleTable, TupleDesc desc, const TupleTableSlotOps *tts_ops, uint16 flags)
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
static void tts_virtual_materialize(TupleTableSlot *slot)
Definition execTuples.c:176
TupleDesc ExecTypeFromTL(List *targetList)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
static bool tts_minimal_is_current_xact_tuple(TupleTableSlot *slot)
Definition execTuples.c:575
static MinimalTuple tts_minimal_copy_minimal_tuple(TupleTableSlot *slot, Size extra)
Definition execTuples.c:671
static HeapTuple tts_heap_get_heap_tuple(TupleTableSlot *slot)
Definition execTuples.c:452
static void tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
Definition execTuples.c:544
static void tts_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition execTuples.c:439
TupleTableSlot * ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, const TupleTableSlotOps *tts_ops)
static void tts_heap_clear(TupleTableSlot *slot)
Definition execTuples.c:327
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
static void tts_heap_getsomeattrs(TupleTableSlot *slot, int natts)
Definition execTuples.c:346
static void tts_heap_release(TupleTableSlot *slot)
Definition execTuples.c:322
static void tts_buffer_heap_init(TupleTableSlot *slot)
Definition execTuples.c:711
static bool tts_heap_is_current_xact_tuple(TupleTableSlot *slot)
Definition execTuples.c:376
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
static Datum tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition execTuples.c:141
int ExecTargetListLength(List *targetlist)
Definition execUtils.c:1201
int ExecCleanTargetListLength(List *targetlist)
Definition execUtils.c:1211
ExpandedObjectHeader * DatumGetEOHP(Datum d)
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
#define palloc_object(type)
Definition fe_memutils.h:89
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition fmgr.c:1532
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
#define DatumGetHeapTupleHeader(X)
Definition fmgr.h:296
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:686
MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup, Size extra)
Definition heaptuple.c:1478
Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition heaptuple.c:633
MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull, Size extra)
Definition heaptuple.c:1390
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
void heap_free_minimal_tuple(MinimalTuple mtup)
Definition heaptuple.c:1466
MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup, Size extra)
Definition heaptuple.c:1523
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition heaptuple.c:1254
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition heaptuple.c:989
HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)
Definition heaptuple.c:1501
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
HeapTupleHeaderData * HeapTupleHeader
Definition htup.h:23
#define MINIMAL_TUPLE_OFFSET
#define HeapTupleHeaderGetNatts(tup)
static bool HeapTupleHasNulls(const HeapTupleData *tuple)
static int BITMAPLEN(int NATTS)
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
#define HeapTupleHeaderHasExternal(tup)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
long val
Definition informix.c:689
int i
Definition isn.c:77
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:3182
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1235
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420
void * palloc(Size size)
Definition mcxt.c:1390
MemoryContext CurrentMemoryContext
Definition mcxt.c:161
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:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
#define IsA(nodeptr, _type_)
Definition nodes.h:164
@ CMD_SELECT
Definition nodes.h:275
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
int16 attnum
int16 attlen
FormData_pg_attribute * Form_pg_attribute
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
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#define PointerGetDatum(X)
Definition postgres.h:354
unsigned int Oid
e
static int fb(int x)
#define init()
FmgrInfo * attinfuncs
Definition funcapi.h:41
TupleDesc tupdesc
Definition funcapi.h:38
Oid * attioparams
Definition funcapi.h:44
int32 * atttypmods
Definition funcapi.h:47
uint8 attalignby
Definition tupdesc.h:74
bool attisdropped
Definition tupdesc.h:78
List * es_tupleTable
Definition execnodes.h:749
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 pg_list.h:54
Definition nodes.h:135
const TupleTableSlotOps * resultops
Definition execnodes.h:1281
bool resultopsset
Definition execnodes.h:1289
Plan * plan
Definition execnodes.h:1202
EState * state
Definition execnodes.h:1204
TupleDesc ps_ResultTupleDesc
Definition execnodes.h:1241
TupleTableSlot * ps_ResultTupleSlot
Definition execnodes.h:1242
bool resultopsfixed
Definition execnodes.h:1285
List * targetlist
Definition plannodes.h:235
struct AttrMissing * missing
Definition tupdesc.h:42
int firstNonCachedOffsetAttr
Definition tupdesc.h:154
TupleConstr * constr
Definition tupdesc.h:159
int32 tdtypmod
Definition tupdesc.h:152
size_t base_slot_size
Definition tuptable.h:150
HeapTuple(* get_heap_tuple)(TupleTableSlot *slot)
Definition tuptable.h:209
MinimalTuple(* copy_minimal_tuple)(TupleTableSlot *slot, Size extra)
Definition tuptable.h:241
void(* init)(TupleTableSlot *slot)
Definition tuptable.h:153
void(* getsomeattrs)(TupleTableSlot *slot, int natts)
Definition tuptable.h:175
HeapTuple(* copy_heap_tuple)(TupleTableSlot *slot)
Definition tuptable.h:227
MinimalTuple(* get_minimal_tuple)(TupleTableSlot *slot)
Definition tuptable.h:217
void(* materialize)(TupleTableSlot *slot)
Definition tuptable.h:194
void(* release)(TupleTableSlot *slot)
Definition tuptable.h:156
TupleDesc tts_tupleDescriptor
Definition tuptable.h:129
const TupleTableSlotOps *const tts_ops
Definition tuptable.h:127
NodeTag type
Definition tuptable.h:122
MemoryContext tts_mcxt
Definition tuptable.h:141
int tts_first_nonguaranteed
Definition tuptable.h:136
AttrNumber tts_nvalid
Definition tuptable.h:126
bool * tts_isnull
Definition tuptable.h:133
ItemPointerData tts_tid
Definition tuptable.h:142
Datum * tts_values
Definition tuptable.h:131
uint16 tts_flags
Definition tuptable.h:124
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid)
Definition tupdesc.c:1093
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:909
#define ReleaseTupleDesc(tupdesc)
Definition tupdesc.h:240
#define PinTupleDesc(tupdesc)
Definition tupdesc.h:234
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:195
#define att_nominal_alignby(cur_offset, attalignby)
Definition tupmacs.h:411
static void populate_isnull_array(const uint8 *bits, int natts, bool *isnull)
Definition tupmacs.h:43
static Datum align_fetch_then_add(const char *tupptr, uint32 *off, bool attbyval, int attlen, uint8 attalignby)
Definition tupmacs.h:172
static Datum fetch_att_noerr(const void *T, bool attbyval, int attlen)
Definition tupmacs.h:137
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition tupmacs.h:419
static int first_null_attr(const uint8 *bits, int natts)
Definition tupmacs.h:244
#define TTS_FLAG_EMPTY
Definition tuptable.h:91
#define TTS_FLAG_SHOULDFREE
Definition tuptable.h:95
#define TTS_IS_MINIMALTUPLE(slot)
Definition tuptable.h:255
static MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot)
Definition tuptable.h:515
#define TTS_FLAG_FIXED
Definition tuptable.h:107
#define TTS_EMPTY(slot)
Definition tuptable.h:92
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
Definition tuptable.h:504
#define TTS_IS_BUFFERTUPLE(slot)
Definition tuptable.h:256
#define TTS_FIXED(slot)
Definition tuptable.h:108
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476
static void slot_getallattrs(TupleTableSlot *slot)
Definition tuptable.h:390
#define TTS_FLAG_OBEYS_NOT_NULL_CONSTRAINTS
Definition tuptable.h:102
#define TTS_SHOULDFREE(slot)
Definition tuptable.h:96
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition tuptable.h:495
#define TTS_IS_HEAPTUPLE(slot)
Definition tuptable.h:254
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition typcache.c:1940
void assign_record_type_typmod(TupleDesc tupDesc)
Definition typcache.c:2060
#define strVal(v)
Definition value.h:82
static bool VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)
Definition varatt.h:389
text * cstring_to_text_with_len(const char *s, int len)
Definition varlena.c:196
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition xact.c:943