Move generic slot support functions from heaptuple.c into execTuples.c.
authorAndres Freund
Sun, 14 Oct 2018 22:18:16 +0000 (15:18 -0700)
committerAndres Freund
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[email protected]

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