@ -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 ) ;
attrMap = convert_tuples_by_name_map_if_req ( 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 + + )
if ( attrMap = = NULL )
{
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 ) ;
/* runtime conversion is not needed */
return NULL ;
}
@ -367,11 +324,78 @@ convert_tuples_by_name_map(TupleDesc indesc,
return attrMap ;
}
/*
* 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 ;
@ -405,6 +429,62 @@ do_convert_tuple(HeapTuple tuple, TupleConversionMap *map)
return heap_form_tuple ( map - > outdesc , outvalues , outisnull ) ;
}
/*
* 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 .
*/