@ -49,6 +49,12 @@
# include "utils/selfuncs.h"
# include "utils/selfuncs.h"
typedef struct
{
PlannerInfo * root ;
AppendRelInfo * appinfo ;
} adjust_appendrel_attrs_context ;
static Plan * recurse_set_operations ( Node * setOp , PlannerInfo * root ,
static Plan * recurse_set_operations ( Node * setOp , PlannerInfo * root ,
double tuple_fraction ,
double tuple_fraction ,
List * colTypes , List * colCollations ,
List * colTypes , List * colCollations ,
@ -99,7 +105,7 @@ static void make_inh_translation_list(Relation oldrelation,
static Bitmapset * translate_col_privs ( const Bitmapset * parent_privs ,
static Bitmapset * translate_col_privs ( const Bitmapset * parent_privs ,
List * translated_vars ) ;
List * translated_vars ) ;
static Node * adjust_appendrel_attrs_mutator ( Node * node ,
static Node * adjust_appendrel_attrs_mutator ( Node * node ,
AppendRelInfo * context ) ;
adjust_appendrel_attrs_context * context ) ;
static Relids adjust_relid_set ( Relids relids , Index oldrelid , Index newrelid ) ;
static Relids adjust_relid_set ( Relids relids , Index oldrelid , Index newrelid ) ;
static List * adjust_inherited_tlist ( List * tlist ,
static List * adjust_inherited_tlist ( List * tlist ,
AppendRelInfo * context ) ;
AppendRelInfo * context ) ;
@ -1569,9 +1575,13 @@ translate_col_privs(const Bitmapset *parent_privs,
* maybe we should try to fold the two routines together .
* maybe we should try to fold the two routines together .
*/
*/
Node *
Node *
adjust_appendrel_attrs ( Node * node , AppendRelInfo * appinfo )
adjust_appendrel_attrs ( PlannerInfo * root , Node * node , AppendRelInfo * appinfo )
{
{
Node * result ;
Node * result ;
adjust_appendrel_attrs_context context ;
context . root = root ;
context . appinfo = appinfo ;
/*
/*
* Must be prepared to start with a Query or a bare expression tree .
* Must be prepared to start with a Query or a bare expression tree .
@ -1582,7 +1592,7 @@ adjust_appendrel_attrs(Node *node, AppendRelInfo *appinfo)
newnode = query_tree_mutator ( ( Query * ) node ,
newnode = query_tree_mutator ( ( Query * ) node ,
adjust_appendrel_attrs_mutator ,
adjust_appendrel_attrs_mutator ,
( void * ) appinfo ,
( void * ) & context ,
QTW_IGNORE_RC_SUBQUERIES ) ;
QTW_IGNORE_RC_SUBQUERIES ) ;
if ( newnode - > resultRelation = = appinfo - > parent_relid )
if ( newnode - > resultRelation = = appinfo - > parent_relid )
{
{
@ -1596,14 +1606,17 @@ adjust_appendrel_attrs(Node *node, AppendRelInfo *appinfo)
result = ( Node * ) newnode ;
result = ( Node * ) newnode ;
}
}
else
else
result = adjust_appendrel_attrs_mutator ( node , appinfo ) ;
result = adjust_appendrel_attrs_mutator ( node , & context ) ;
return result ;
return result ;
}
}
static Node *
static Node *
adjust_appendrel_attrs_mutator ( Node * node , AppendRelInfo * context )
adjust_appendrel_attrs_mutator ( Node * node ,
adjust_appendrel_attrs_context * context )
{
{
AppendRelInfo * appinfo = context - > appinfo ;
if ( node = = NULL )
if ( node = = NULL )
return NULL ;
return NULL ;
if ( IsA ( node , Var ) )
if ( IsA ( node , Var ) )
@ -1611,22 +1624,22 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
Var * var = ( Var * ) copyObject ( node ) ;
Var * var = ( Var * ) copyObject ( node ) ;
if ( var - > varlevelsup = = 0 & &
if ( var - > varlevelsup = = 0 & &
var - > varno = = context - > parent_relid )
var - > varno = = appinfo - > parent_relid )
{
{
var - > varno = context - > child_relid ;
var - > varno = appinfo - > child_relid ;
var - > varnoold = context - > child_relid ;
var - > varnoold = appinfo - > child_relid ;
if ( var - > varattno > 0 )
if ( var - > varattno > 0 )
{
{
Node * newnode ;
Node * newnode ;
if ( var - > varattno > list_length ( context - > translated_vars ) )
if ( var - > varattno > list_length ( appinfo - > translated_vars ) )
elog ( ERROR , " attribute %d of relation \" %s \" does not exist " ,
elog ( ERROR , " attribute %d of relation \" %s \" does not exist " ,
var - > varattno , get_rel_name ( context - > parent_reloid ) ) ;
var - > varattno , get_rel_name ( appinfo - > parent_reloid ) ) ;
newnode = copyObject ( list_nth ( context - > translated_vars ,
newnode = copyObject ( list_nth ( appinfo - > translated_vars ,
var - > varattno - 1 ) ) ;
var - > varattno - 1 ) ) ;
if ( newnode = = NULL )
if ( newnode = = NULL )
elog ( ERROR , " attribute %d of relation \" %s \" does not exist " ,
elog ( ERROR , " attribute %d of relation \" %s \" does not exist " ,
var - > varattno , get_rel_name ( context - > parent_reloid ) ) ;
var - > varattno , get_rel_name ( appinfo - > parent_reloid ) ) ;
return newnode ;
return newnode ;
}
}
else if ( var - > varattno = = 0 )
else if ( var - > varattno = = 0 )
@ -1637,19 +1650,19 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
* step to convert the tuple layout to the parent ' s rowtype .
* step to convert the tuple layout to the parent ' s rowtype .
* Otherwise we have to generate a RowExpr .
* Otherwise we have to generate a RowExpr .
*/
*/
if ( OidIsValid ( context - > child_reltype ) )
if ( OidIsValid ( appinfo - > child_reltype ) )
{
{
Assert ( var - > vartype = = context - > parent_reltype ) ;
Assert ( var - > vartype = = appinfo - > parent_reltype ) ;
if ( context - > parent_reltype ! = context - > child_reltype )
if ( appinfo - > parent_reltype ! = appinfo - > child_reltype )
{
{
ConvertRowtypeExpr * r = makeNode ( ConvertRowtypeExpr ) ;
ConvertRowtypeExpr * r = makeNode ( ConvertRowtypeExpr ) ;
r - > arg = ( Expr * ) var ;
r - > arg = ( Expr * ) var ;
r - > resulttype = context - > parent_reltype ;
r - > resulttype = appinfo - > parent_reltype ;
r - > convertformat = COERCE_IMPLICIT_CAST ;
r - > convertformat = COERCE_IMPLICIT_CAST ;
r - > location = - 1 ;
r - > location = - 1 ;
/* Make sure the Var node has the right type ID, too */
/* Make sure the Var node has the right type ID, too */
var - > vartype = context - > child_reltype ;
var - > vartype = appinfo - > child_reltype ;
return ( Node * ) r ;
return ( Node * ) r ;
}
}
}
}
@ -1657,16 +1670,27 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
{
{
/*
/*
* Build a RowExpr containing the translated variables .
* Build a RowExpr containing the translated variables .
*
* In practice var - > vartype will always be RECORDOID here ,
* so we need to come up with some suitable column names .
* We use the parent RTE ' s column names .
*
* Note : we can ' t get here for inheritance cases , so there
* is no need to worry that translated_vars might contain
* some dummy NULLs .
*/
*/
RowExpr * rowexpr ;
RowExpr * rowexpr ;
List * fields ;
List * fields ;
RangeTblEntry * rte ;
fields = ( List * ) copyObject ( context - > translated_vars ) ;
rte = rt_fetch ( appinfo - > parent_relid ,
context - > root - > parse - > rtable ) ;
fields = ( List * ) copyObject ( appinfo - > translated_vars ) ;
rowexpr = makeNode ( RowExpr ) ;
rowexpr = makeNode ( RowExpr ) ;
rowexpr - > args = fields ;
rowexpr - > args = fields ;
rowexpr - > row_typeid = var - > vartype ;
rowexpr - > row_typeid = var - > vartype ;
rowexpr - > row_format = COERCE_IMPLICIT_CAST ;
rowexpr - > row_format = COERCE_IMPLICIT_CAST ;
rowexpr - > colnames = NIL ;
rowexpr - > colnames = copyObject ( rte - > eref - > colnames ) ;
rowexpr - > location = - 1 ;
rowexpr - > location = - 1 ;
return ( Node * ) rowexpr ;
return ( Node * ) rowexpr ;
@ -1680,16 +1704,16 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
{
{
CurrentOfExpr * cexpr = ( CurrentOfExpr * ) copyObject ( node ) ;
CurrentOfExpr * cexpr = ( CurrentOfExpr * ) copyObject ( node ) ;
if ( cexpr - > cvarno = = context - > parent_relid )
if ( cexpr - > cvarno = = appinfo - > parent_relid )
cexpr - > cvarno = context - > child_relid ;
cexpr - > cvarno = appinfo - > child_relid ;
return ( Node * ) cexpr ;
return ( Node * ) cexpr ;
}
}
if ( IsA ( node , RangeTblRef ) )
if ( IsA ( node , RangeTblRef ) )
{
{
RangeTblRef * rtr = ( RangeTblRef * ) copyObject ( node ) ;
RangeTblRef * rtr = ( RangeTblRef * ) copyObject ( node ) ;
if ( rtr - > rtindex = = context - > parent_relid )
if ( rtr - > rtindex = = appinfo - > parent_relid )
rtr - > rtindex = context - > child_relid ;
rtr - > rtindex = appinfo - > child_relid ;
return ( Node * ) rtr ;
return ( Node * ) rtr ;
}
}
if ( IsA ( node , JoinExpr ) )
if ( IsA ( node , JoinExpr ) )
@ -1701,8 +1725,8 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
adjust_appendrel_attrs_mutator ,
adjust_appendrel_attrs_mutator ,
( void * ) context ) ;
( void * ) context ) ;
/* now fix JoinExpr's rtindex (probably never happens) */
/* now fix JoinExpr's rtindex (probably never happens) */
if ( j - > rtindex = = context - > parent_relid )
if ( j - > rtindex = = appinfo - > parent_relid )
j - > rtindex = context - > child_relid ;
j - > rtindex = appinfo - > child_relid ;
return ( Node * ) j ;
return ( Node * ) j ;
}
}
if ( IsA ( node , PlaceHolderVar ) )
if ( IsA ( node , PlaceHolderVar ) )
@ -1716,8 +1740,8 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
/* now fix PlaceHolderVar's relid sets */
/* now fix PlaceHolderVar's relid sets */
if ( phv - > phlevelsup = = 0 )
if ( phv - > phlevelsup = = 0 )
phv - > phrels = adjust_relid_set ( phv - > phrels ,
phv - > phrels = adjust_relid_set ( phv - > phrels ,
context - > parent_relid ,
appinfo - > parent_relid ,
context - > child_relid ) ;
appinfo - > child_relid ) ;
return ( Node * ) phv ;
return ( Node * ) phv ;
}
}
/* Shouldn't need to handle planner auxiliary nodes here */
/* Shouldn't need to handle planner auxiliary nodes here */
@ -1749,20 +1773,20 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
/* adjust relid sets too */
/* adjust relid sets too */
newinfo - > clause_relids = adjust_relid_set ( oldinfo - > clause_relids ,
newinfo - > clause_relids = adjust_relid_set ( oldinfo - > clause_relids ,
context - > parent_relid ,
appinfo - > parent_relid ,
context - > child_relid ) ;
appinfo - > child_relid ) ;
newinfo - > required_relids = adjust_relid_set ( oldinfo - > required_relids ,
newinfo - > required_relids = adjust_relid_set ( oldinfo - > required_relids ,
context - > parent_relid ,
appinfo - > parent_relid ,
context - > child_relid ) ;
appinfo - > child_relid ) ;
newinfo - > nullable_relids = adjust_relid_set ( oldinfo - > nullable_relids ,
newinfo - > nullable_relids = adjust_relid_set ( oldinfo - > nullable_relids ,
context - > parent_relid ,
appinfo - > parent_relid ,
context - > child_relid ) ;
appinfo - > child_relid ) ;
newinfo - > left_relids = adjust_relid_set ( oldinfo - > left_relids ,
newinfo - > left_relids = adjust_relid_set ( oldinfo - > left_relids ,
context - > parent_relid ,
appinfo - > parent_relid ,
context - > child_relid ) ;
appinfo - > child_relid ) ;
newinfo - > right_relids = adjust_relid_set ( oldinfo - > right_relids ,
newinfo - > right_relids = adjust_relid_set ( oldinfo - > right_relids ,
context - > parent_relid ,
appinfo - > parent_relid ,
context - > child_relid ) ;
appinfo - > child_relid ) ;
/*
/*
* Reset cached derivative fields , since these might need to have
* Reset cached derivative fields , since these might need to have