aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/common/tupconvert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/common/tupconvert.c')
-rw-r--r--src/backend/access/common/tupconvert.c182
1 files changed, 131 insertions, 51 deletions
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 3bc67b846d4..21fe8ae4909 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -4,10 +4,8 @@
* Tuple conversion support.
*
* These functions provide conversion between rowtypes that are logically
- * equivalent but might have columns in a different order or different sets
- * of dropped columns. There is some overlap of functionality with the
- * executor's "junkfilter" routines, but these functions work on bare
- * HeapTuples rather than TupleTableSlots.
+ * equivalent but might have columns in a different order or different sets of
+ * dropped columns.
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
@@ -22,6 +20,7 @@
#include "access/htup_details.h"
#include "access/tupconvert.h"
+#include "executor/tuptable.h"
#include "utils/builtins.h"
@@ -31,7 +30,7 @@
* The setup routine checks whether the given source and destination tuple
* descriptors are logically compatible. If not, it throws an error.
* If so, it returns NULL if they are physically compatible (ie, no conversion
- * is needed), else a TupleConversionMap that can be used by do_convert_tuple
+ * is needed), else a TupleConversionMap that can be used by execute_attr_map_tuple
* to perform the conversion.
*
* The TupleConversionMap, if needed, is palloc'd in the caller's memory
@@ -214,55 +213,13 @@ convert_tuples_by_name(TupleDesc indesc,
TupleConversionMap *map;
AttrNumber *attrMap;
int n = outdesc->natts;
- int i;
- bool same;
/* Verify compatibility and prepare attribute-number map */
- attrMap = convert_tuples_by_name_map(indesc, outdesc, msg);
-
- /*
- * Check to see if the map is one-to-one, in which case we need not do a
- * tuple conversion. We must also insist that both tupdescs either
- * specify or don't specify an OID column, else we need a conversion to
- * add/remove space for that. (For some callers, presence or absence of
- * an OID column perhaps would not really matter, but let's be safe.)
- */
- if (indesc->natts == outdesc->natts &&
- indesc->tdhasoid == outdesc->tdhasoid)
- {
- same = true;
- for (i = 0; i < n; i++)
- {
- Form_pg_attribute inatt;
- Form_pg_attribute outatt;
-
- if (attrMap[i] == (i + 1))
- continue;
-
- /*
- * If it's a dropped column and the corresponding input column is
- * also dropped, we needn't convert. However, attlen and attalign
- * must agree.
- */
- inatt = TupleDescAttr(indesc, i);
- outatt = TupleDescAttr(outdesc, i);
- if (attrMap[i] == 0 &&
- inatt->attisdropped &&
- inatt->attlen == outatt->attlen &&
- inatt->attalign == outatt->attalign)
- continue;
-
- same = false;
- break;
- }
- }
- else
- same = false;
+ attrMap = convert_tuples_by_name_map_if_req(indesc, outdesc, msg);
- if (same)
+ if (attrMap == NULL)
{
- /* Runtime conversion is not needed */
- pfree(attrMap);
+ /* runtime conversion is not needed */
return NULL;
}
@@ -368,10 +325,77 @@ convert_tuples_by_name_map(TupleDesc indesc,
}
/*
+ * Returns mapping created by convert_tuples_by_name_map, or NULL if no
+ * conversion not required. This is a convenience routine for
+ * convert_tuples_by_name() and other functions.
+ */
+AttrNumber *
+convert_tuples_by_name_map_if_req(TupleDesc indesc,
+ TupleDesc outdesc,
+ const char *msg)
+{
+ AttrNumber *attrMap;
+ int n = outdesc->natts;
+ int i;
+ bool same;
+
+ /* Verify compatibility and prepare attribute-number map */
+ attrMap = convert_tuples_by_name_map(indesc, outdesc, msg);
+
+ /*
+ * Check to see if the map is one-to-one, in which case we need not do a
+ * tuple conversion. We must also insist that both tupdescs either
+ * specify or don't specify an OID column, else we need a conversion to
+ * add/remove space for that. (For some callers, presence or absence of
+ * an OID column perhaps would not really matter, but let's be safe.)
+ */
+ if (indesc->natts == outdesc->natts &&
+ indesc->tdhasoid == outdesc->tdhasoid)
+ {
+ same = true;
+ for (i = 0; i < n; i++)
+ {
+ Form_pg_attribute inatt;
+ Form_pg_attribute outatt;
+
+ if (attrMap[i] == (i + 1))
+ continue;
+
+ /*
+ * If it's a dropped column and the corresponding input column is
+ * also dropped, we needn't convert. However, attlen and attalign
+ * must agree.
+ */
+ inatt = TupleDescAttr(indesc, i);
+ outatt = TupleDescAttr(outdesc, i);
+ if (attrMap[i] == 0 &&
+ inatt->attisdropped &&
+ inatt->attlen == outatt->attlen &&
+ inatt->attalign == outatt->attalign)
+ continue;
+
+ same = false;
+ break;
+ }
+ }
+ else
+ same = false;
+
+ if (same)
+ {
+ /* Runtime conversion is not needed */
+ pfree(attrMap);
+ return NULL;
+ }
+ else
+ return attrMap;
+}
+
+/*
* Perform conversion of a tuple according to the map.
*/
HeapTuple
-do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
+execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map)
{
AttrNumber *attrMap = map->attrMap;
Datum *invalues = map->invalues;
@@ -406,6 +430,62 @@ do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
}
/*
+ * Perform conversion of a tuple slot according to the map.
+ */
+TupleTableSlot *
+execute_attr_map_slot(AttrNumber *attrMap,
+ TupleTableSlot *in_slot,
+ TupleTableSlot *out_slot)
+{
+ Datum *invalues;
+ bool *inisnull;
+ Datum *outvalues;
+ bool *outisnull;
+ int outnatts;
+ int i;
+
+ /* Sanity checks */
+ Assert(in_slot->tts_tupleDescriptor != NULL &&
+ out_slot->tts_tupleDescriptor != NULL);
+ Assert(in_slot->tts_values != NULL && out_slot->tts_values != NULL);
+
+ outnatts = out_slot->tts_tupleDescriptor->natts;
+
+ /* Extract all the values of the in slot. */
+ slot_getallattrs(in_slot);
+
+ /* Before doing the mapping, clear any old contents from the out slot */
+ ExecClearTuple(out_slot);
+
+ invalues = in_slot->tts_values;
+ inisnull = in_slot->tts_isnull;
+ outvalues = out_slot->tts_values;
+ outisnull = out_slot->tts_isnull;
+
+ /* Transpose into proper fields of the out slot. */
+ for (i = 0; i < outnatts; i++)
+ {
+ int j = attrMap[i] - 1;
+
+ /* attrMap[i] == 0 means it's a NULL datum. */
+ if (j == -1)
+ {
+ outvalues[i] = (Datum) 0;
+ outisnull[i] = true;
+ }
+ else
+ {
+ outvalues[i] = invalues[j];
+ outisnull[i] = inisnull[j];
+ }
+ }
+
+ ExecStoreVirtualTuple(out_slot);
+
+ return out_slot;
+}
+
+/*
* Free a TupleConversionMap structure.
*/
void