diff options
Diffstat (limited to 'src/backend/access/common/tupconvert.c')
-rw-r--r-- | src/backend/access/common/tupconvert.c | 182 |
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 |