Move generic slot support functions from heaptuple.c into execTuples.c.
authorAndres Freund <andres@anarazel.de>
Sun, 14 Oct 2018 22:18:16 +0000 (15:18 -0700)
committerAndres Freund <andres@anarazel.de>
Mon, 15 Oct 2018 22:17:04 +0000 (15:17 -0700)
heaptuple.c was never a particular good fit for slot_getattr(),
slot_getsomeattrs() and slot_getmissingattrs(), but in upcoming
changes slots will be made more abstract (allowing slots that contain
different types of tuples), making it clearly the wrong place.

Note that slot_deform_tuple() remains in it's current place, as it
clearly deals with a HeapTuple.  getmissingattrs() also remains, but
it's less clear that that's correct - but execTuples.c wouldn't be the
right place.

Author: Ashutosh Bapat.
Discussion: https://postgr.es/m/20180220224318.gw4oe5jadhpmcdnm@alap3.anarazel.de

src/backend/access/common/heaptuple.c
src/backend/executor/execTuples.c
src/include/access/htup_details.h
src/include/executor/tuptable.h

index 7fc2fee74abbcbe6cb3ab1ccc29643508787351b..6b4863b33a9d70651d08094099b614efda443985 100644 (file)
@@ -80,7 +80,7 @@
 /*
  * Return the missing value of an attribute, or NULL if there isn't one.
  */
-static Datum
+Datum
 getmissingattr(TupleDesc tupleDesc,
                           int attnum, bool *isnull)
 {
@@ -111,43 +111,6 @@ getmissingattr(TupleDesc tupleDesc,
        return PointerGetDatum(NULL);
 }
 
-/*
- * 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;
-               }
-       }
-}
-
 /*
  * heap_compute_data_size
  *             Determine size of the data area of a tuple to be constructed
@@ -1398,7 +1361,7 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
  *             re-computing information about previously extracted attributes.
  *             slot->tts_nvalid is the number of attributes already extracted.
  */
-static void
+void
 slot_deform_tuple(TupleTableSlot *slot, int natts)
 {
        HeapTuple       tuple = slot->tts_tuple;
@@ -1492,153 +1455,6 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
        slot->tts_slow = slow;
 }
 
-/*
- * 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;
-}
-
 /*
  * slot_attisnull
  *             Detect whether an attribute of the slot is null, without
index 716c04939cdb6a1c355196b2ef9d2746be509a2f..fbbac1c6bf81f7095c40cbcdc4ee3f91bf656484 100644 (file)
@@ -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
  *
index 1867a70f6f3a029c4f15c69c8fea6ace8667c2b1..97d240fdbb05f672a247e5d27442803a42f3caa1 100644 (file)
@@ -835,5 +835,7 @@ extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
 extern size_t varsize_any(void *p);
 extern HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
 extern MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
+struct TupleTableSlot;
+extern void slot_deform_tuple(struct TupleTableSlot *slot, int natts);
 
 #endif                                                 /* HTUP_DETAILS_H */
index 43150d13b1e9f26d8e2d69327c6a5121228b38e7..3c8d57f37766a3c3ac9a3ba9c816d789fe43285e 100644 (file)
@@ -173,14 +173,18 @@ extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);
 extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot);
 extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
                         TupleTableSlot *srcslot);
+extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
+                                        int lastAttNum);
+extern Datum slot_getattr(TupleTableSlot *slot, int attnum,
+                        bool *isnull);
+extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
 
 /* in access/common/heaptuple.c */
-extern Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull);
-extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
 extern bool slot_attisnull(TupleTableSlot *slot, int attnum);
 extern bool slot_getsysattr(TupleTableSlot *slot, int attnum,
                                Datum *value, bool *isnull);
-extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum);
+extern Datum getmissingattr(TupleDesc tupleDesc,
+                          int attnum, bool *isnull);
 
 #ifndef FRONTEND