@ -923,13 +923,19 @@ RelationGetPartitionQual(Relation rel, bool recurse)
return generate_partition_qual ( rel , recurse ) ;
}
/* Turn an array of OIDs with N elements into a list */
# define OID_ARRAY_TO_LIST(arr, N, list) \
/*
* Append OIDs of rel ' s partitions to the list ' partoids ' and for each OID ,
* append pointer rel to the list ' parents ' .
*/
# define APPEND_REL_PARTITION_OIDS(rel, partoids, parents) \
do \
{ \
int i ; \
for ( i = 0 ; i < ( N ) ; i + + ) \
( list ) = lappend_oid ( ( list ) , ( arr ) [ i ] ) ; \
for ( i = 0 ; i < ( rel ) - > rd_partdesc - > nparts ; i + + ) \
{ \
( partoids ) = lappend_oid ( ( partoids ) , ( rel ) - > rd_partdesc - > oids [ i ] ) ; \
( parents ) = lappend ( ( parents ) , ( rel ) ) ; \
} \
} while ( 0 )
/*
@ -944,11 +950,13 @@ PartitionDispatch *
RelationGetPartitionDispatchInfo ( Relation rel , int lockmode ,
int * num_parted , List * * leaf_part_oids )
{
PartitionDesc rootpartdesc = RelationGetPartitionDesc ( rel ) ;
PartitionDispatchData * * pd ;
List * all_parts = NIL ,
* parted_rels ;
ListCell * lc ;
* all_parents = NIL ,
* parted_rels ,
* parted_rel_parents ;
ListCell * lc1 ,
* lc2 ;
int i ,
k ,
offset ;
@ -965,10 +973,13 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
*/
* num_parted = 1 ;
parted_rels = list_make1 ( rel ) ;
OID_ARRAY_TO_LIST ( rootpartdesc - > oids , rootpartdesc - > nparts , all_parts ) ;
foreach ( lc , all_parts )
/* Root partitioned table has no parent, so NULL for parent */
parted_rel_parents = list_make1 ( NULL ) ;
APPEND_REL_PARTITION_OIDS ( rel , all_parts , all_parents ) ;
forboth ( lc1 , all_parts , lc2 , all_parents )
{
Relation partrel = heap_open ( lfirst_oid ( lc ) , lockmode ) ;
Relation partrel = heap_open ( lfirst_oid ( lc1 ) , lockmode ) ;
Relation parent = lfirst ( lc2 ) ;
PartitionDesc partdesc = RelationGetPartitionDesc ( partrel ) ;
/*
@ -979,7 +990,8 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
{
( * num_parted ) + + ;
parted_rels = lappend ( parted_rels , partrel ) ;
OID_ARRAY_TO_LIST ( partdesc - > oids , partdesc - > nparts , all_parts ) ;
parted_rel_parents = lappend ( parted_rel_parents , parent ) ;
APPEND_REL_PARTITION_OIDS ( partrel , all_parts , all_parents ) ;
}
else
heap_close ( partrel , NoLock ) ;
@ -1004,10 +1016,12 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
sizeof ( PartitionDispatchData * ) ) ;
* leaf_part_oids = NIL ;
i = k = offset = 0 ;
foreac h ( lc , parted_rels )
forbot h ( lc1 , parted_rels , lc2 , parted_rel_parent s )
{
Relation partrel = lfirst ( lc ) ;
Relation partrel = lfirst ( lc1 ) ;
Relation parent = lfirst ( lc2 ) ;
PartitionKey partkey = RelationGetPartitionKey ( partrel ) ;
TupleDesc tupdesc = RelationGetDescr ( partrel ) ;
PartitionDesc partdesc = RelationGetPartitionDesc ( partrel ) ;
int j ,
m ;
@ -1017,6 +1031,27 @@ RelationGetPartitionDispatchInfo(Relation rel, int lockmode,
pd [ i ] - > key = partkey ;
pd [ i ] - > keystate = NIL ;
pd [ i ] - > partdesc = partdesc ;
if ( parent ! = NULL )
{
/*
* For every partitioned table other than root , we must store
* a tuple table slot initialized with its tuple descriptor and
* a tuple conversion map to convert a tuple from its parent ' s
* rowtype to its own . That is to make sure that we are looking
* at the correct row using the correct tuple descriptor when
* computing its partition key for tuple routing .
*/
pd [ i ] - > tupslot = MakeSingleTupleTableSlot ( tupdesc ) ;
pd [ i ] - > tupmap = convert_tuples_by_name ( RelationGetDescr ( parent ) ,
tupdesc ,
gettext_noop ( " could not convert row type " ) ) ;
}
else
{
/* Not required for the root partitioned table */
pd [ i ] - > tupslot = NULL ;
pd [ i ] - > tupmap = NULL ;
}
pd [ i ] - > indexes = ( int * ) palloc ( partdesc - > nparts * sizeof ( int ) ) ;
/*
@ -1610,6 +1645,8 @@ get_partition_for_tuple(PartitionDispatch *pd,
{
PartitionKey key = parent - > key ;
PartitionDesc partdesc = parent - > partdesc ;
TupleTableSlot * myslot = parent - > tupslot ;
TupleConversionMap * map = parent - > tupmap ;
/* Quick exit */
if ( partdesc - > nparts = = 0 )
@ -1618,6 +1655,17 @@ get_partition_for_tuple(PartitionDispatch *pd,
return - 1 ;
}
if ( myslot ! = NULL )
{
HeapTuple tuple = ExecFetchSlotTuple ( slot ) ;
ExecClearTuple ( myslot ) ;
Assert ( map ! = NULL ) ;
tuple = do_convert_tuple ( tuple , map ) ;
ExecStoreTuple ( tuple , myslot , InvalidBuffer , true ) ;
slot = myslot ;
}
/* Extract partition key from tuple */
FormPartitionKeyDatum ( parent , slot , estate , values , isnull ) ;