aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execTuples.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 716c04939cd..fbbac1c6bf8 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -54,6 +54,7 @@
#include "postgres.h"
#include "access/htup_details.h"
+#include "access/tupdesc_details.h"
#include "access/tuptoaster.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
@@ -959,6 +960,195 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
return ExecStoreAllNullTuple(slot);
}
+/* ---------------------------------------------------------------
+ * Routines for setting/accessing attributes in a slot.
+ * ---------------------------------------------------------------
+ */
+
+/*
+ * Fill in missing values for a TupleTableSlot.
+ *
+ * This is only exposed because it's needed for JIT compiled tuple
+ * deforming. That exception aside, there should be no callers outside of this
+ * file.
+ */
+void
+slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
+{
+ AttrMissing *attrmiss = NULL;
+ int missattnum;
+
+ if (slot->tts_tupleDescriptor->constr)
+ attrmiss = slot->tts_tupleDescriptor->constr->missing;
+
+ if (!attrmiss)
+ {
+ /* no missing values array at all, so just fill everything in as NULL */
+ memset(slot->tts_values + startAttNum, 0,
+ (lastAttNum - startAttNum) * sizeof(Datum));
+ memset(slot->tts_isnull + startAttNum, 1,
+ (lastAttNum - startAttNum) * sizeof(bool));
+ }
+ else
+ {
+ /* if there is a missing values array we must process them one by one */
+ for (missattnum = startAttNum;
+ missattnum < lastAttNum;
+ missattnum++)
+ {
+ slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
+ slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
+ }
+ }
+}
+
+/*
+ * slot_getattr
+ * This function fetches an attribute of the slot's current tuple.
+ * It is functionally equivalent to heap_getattr, but fetches of
+ * multiple attributes of the same tuple will be optimized better,
+ * because we avoid O(N^2) behavior from multiple calls of
+ * nocachegetattr(), even when attcacheoff isn't usable.
+ *
+ * A difference from raw heap_getattr is that attnums beyond the
+ * slot's tupdesc's last attribute will be considered NULL even
+ * when the physical tuple is longer than the tupdesc.
+ */
+Datum
+slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ HeapTuple tuple = slot->tts_tuple;
+ TupleDesc tupleDesc = slot->tts_tupleDescriptor;
+ HeapTupleHeader tup;
+
+ /*
+ * system attributes are handled by heap_getsysattr
+ */
+ if (attnum <= 0)
+ {
+ if (tuple == NULL) /* internal error */
+ elog(ERROR, "cannot extract system attribute from virtual tuple");
+ if (tuple == &(slot->tts_minhdr)) /* internal error */
+ elog(ERROR, "cannot extract system attribute from minimal tuple");
+ return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
+ }
+
+ /*
+ * fast path if desired attribute already cached
+ */
+ if (attnum <= slot->tts_nvalid)
+ {
+ *isnull = slot->tts_isnull[attnum - 1];
+ return slot->tts_values[attnum - 1];
+ }
+
+ /*
+ * return NULL if attnum is out of range according to the tupdesc
+ */
+ if (attnum > tupleDesc->natts)
+ {
+ *isnull = true;
+ return (Datum) 0;
+ }
+
+ /*
+ * otherwise we had better have a physical tuple (tts_nvalid should equal
+ * natts in all virtual-tuple cases)
+ */
+ if (tuple == NULL) /* internal error */
+ elog(ERROR, "cannot extract attribute from empty tuple slot");
+
+ /*
+ * return NULL or missing value if attnum is out of range according to the
+ * tuple
+ *
+ * (We have to check this separately because of various inheritance and
+ * table-alteration scenarios: the tuple could be either longer or shorter
+ * than the tupdesc.)
+ */
+ tup = tuple->t_data;
+ if (attnum > HeapTupleHeaderGetNatts(tup))
+ return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
+
+ /*
+ * check if target attribute is null: no point in groveling through tuple
+ */
+ if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
+ {
+ *isnull = true;
+ return (Datum) 0;
+ }
+
+ /*
+ * If the attribute's column has been dropped, we force a NULL result.
+ * This case should not happen in normal use, but it could happen if we
+ * are executing a plan cached before the column was dropped.
+ */
+ if (TupleDescAttr(tupleDesc, attnum - 1)->attisdropped)
+ {
+ *isnull = true;
+ return (Datum) 0;
+ }
+
+ /*
+ * Extract the attribute, along with any preceding attributes.
+ */
+ slot_deform_tuple(slot, attnum);
+
+ /*
+ * The result is acquired from tts_values array.
+ */
+ *isnull = slot->tts_isnull[attnum - 1];
+ return slot->tts_values[attnum - 1];
+}
+
+/*
+ * slot_getsomeattrs
+ * This function forces the entries of the slot's Datum/isnull
+ * arrays to be valid at least up through the attnum'th entry.
+ */
+void
+slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+{
+ HeapTuple tuple;
+ int attno;
+
+ /* Quick out if we have 'em all already */
+ if (slot->tts_nvalid >= attnum)
+ return;
+
+ /* Check for caller error */
+ if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
+ elog(ERROR, "invalid attribute number %d", attnum);
+
+ /*
+ * otherwise we had better have a physical tuple (tts_nvalid should equal
+ * natts in all virtual-tuple cases)
+ */
+ tuple = slot->tts_tuple;
+ if (tuple == NULL) /* internal error */
+ elog(ERROR, "cannot extract attribute from empty tuple slot");
+
+ /*
+ * load up any slots available from physical tuple
+ */
+ attno = HeapTupleHeaderGetNatts(tuple->t_data);
+ attno = Min(attno, attnum);
+
+ slot_deform_tuple(slot, attno);
+
+ attno = slot->tts_nvalid;
+
+ /*
+ * If tuple doesn't have all the atts indicated by attnum, read the rest
+ * as NULLs or missing values
+ */
+ if (attno < attnum)
+ slot_getmissingattrs(slot, attno, attnum);
+
+ slot->tts_nvalid = attnum;
+}
+
/* ----------------------------------------------------------------
* ExecTypeFromTL
*