@ -392,6 +392,11 @@ static void get_rule_windowspec(WindowClause *wc, List *targetList,
deparse_context * context ) ;
static char * get_variable ( Var * var , int levelsup , bool istoplevel ,
deparse_context * context ) ;
static void get_special_variable ( Node * node , deparse_context * context ,
void * private ) ;
static void resolve_special_varno ( Node * node , deparse_context * context ,
void * private ,
void ( * callback ) ( Node * , deparse_context * , void * ) ) ;
static Node * find_param_referent ( Param * param , deparse_context * context ,
deparse_namespace * * dpns_p , ListCell * * ancestor_cell_p ) ;
static void get_parameter ( Param * param , deparse_context * context ) ;
@ -407,7 +412,10 @@ static void get_rule_expr_toplevel(Node *node, deparse_context *context,
static void get_oper_expr ( OpExpr * expr , deparse_context * context ) ;
static void get_func_expr ( FuncExpr * expr , deparse_context * context ,
bool showimplicit ) ;
static void get_agg_expr ( Aggref * aggref , deparse_context * context ) ;
static void get_agg_expr ( Aggref * aggref , deparse_context * context ,
Aggref * original_aggref ) ;
static void get_agg_combine_expr ( Node * node , deparse_context * context ,
void * private ) ;
static void get_windowfunc_expr ( WindowFunc * wfunc , deparse_context * context ) ;
static void get_coercion_expr ( Node * arg , deparse_context * context ,
Oid resulttype , int32 resulttypmod ,
@ -5877,7 +5885,6 @@ get_utility_query_def(Query *query, deparse_context *context)
}
}
/*
* Display a Var appropriately .
*
@ -5930,82 +5937,11 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
colinfo = deparse_columns_fetch ( var - > varno , dpns ) ;
attnum = var - > varattno ;
}
else if ( var - > varno = = OUTER_VAR & & dpns - > outer_tlist )
{
TargetEntry * tle ;
deparse_namespace save_dpns ;
tle = get_tle_by_resno ( dpns - > outer_tlist , var - > varattno ) ;
if ( ! tle )
elog ( ERROR , " bogus varattno for OUTER_VAR var: %d " , var - > varattno ) ;
Assert ( netlevelsup = = 0 ) ;
push_child_plan ( dpns , dpns - > outer_planstate , & save_dpns ) ;
/*
* Force parentheses because our caller probably assumed a Var is a
* simple expression .
*/
if ( ! IsA ( tle - > expr , Var ) )
appendStringInfoChar ( buf , ' ( ' ) ;
get_rule_expr ( ( Node * ) tle - > expr , context , true ) ;
if ( ! IsA ( tle - > expr , Var ) )
appendStringInfoChar ( buf , ' ) ' ) ;
pop_child_plan ( dpns , & save_dpns ) ;
return NULL ;
}
else if ( var - > varno = = INNER_VAR & & dpns - > inner_tlist )
{
TargetEntry * tle ;
deparse_namespace save_dpns ;
tle = get_tle_by_resno ( dpns - > inner_tlist , var - > varattno ) ;
if ( ! tle )
elog ( ERROR , " bogus varattno for INNER_VAR var: %d " , var - > varattno ) ;
Assert ( netlevelsup = = 0 ) ;
push_child_plan ( dpns , dpns - > inner_planstate , & save_dpns ) ;
/*
* Force parentheses because our caller probably assumed a Var is a
* simple expression .
*/
if ( ! IsA ( tle - > expr , Var ) )
appendStringInfoChar ( buf , ' ( ' ) ;
get_rule_expr ( ( Node * ) tle - > expr , context , true ) ;
if ( ! IsA ( tle - > expr , Var ) )
appendStringInfoChar ( buf , ' ) ' ) ;
pop_child_plan ( dpns , & save_dpns ) ;
return NULL ;
}
else if ( var - > varno = = INDEX_VAR & & dpns - > index_tlist )
{
TargetEntry * tle ;
tle = get_tle_by_resno ( dpns - > index_tlist , var - > varattno ) ;
if ( ! tle )
elog ( ERROR , " bogus varattno for INDEX_VAR var: %d " , var - > varattno ) ;
Assert ( netlevelsup = = 0 ) ;
/*
* Force parentheses because our caller probably assumed a Var is a
* simple expression .
*/
if ( ! IsA ( tle - > expr , Var ) )
appendStringInfoChar ( buf , ' ( ' ) ;
get_rule_expr ( ( Node * ) tle - > expr , context , true ) ;
if ( ! IsA ( tle - > expr , Var ) )
appendStringInfoChar ( buf , ' ) ' ) ;
return NULL ;
}
else
{
elog ( ERROR , " bogus varno: %d " , var - > varno ) ;
return NULL ; /* keep compiler quiet */
resolve_special_varno ( ( Node * ) var , context , NULL ,
get_special_variable ) ;
return NULL ;
}
/*
@ -6118,6 +6054,101 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
return attname ;
}
/*
* Deparse a Var which references OUTER_VAR , INNER_VAR , or INDEX_VAR . This
* routine is actually a callback for get_special_varno , which handles finding
* the correct TargetEntry . We get the expression contained in that
* TargetEntry and just need to deparse it , a job we can throw back on
* get_rule_expr .
*/
static void
get_special_variable ( Node * node , deparse_context * context , void * private )
{
StringInfo buf = context - > buf ;
/*
* Force parentheses because our caller probably assumed a Var is a simple
* expression .
*/
if ( ! IsA ( node , Var ) )
appendStringInfoChar ( buf , ' ( ' ) ;
get_rule_expr ( node , context , true ) ;
if ( ! IsA ( node , Var ) )
appendStringInfoChar ( buf , ' ) ' ) ;
}
/*
* Chase through plan references to special varnos ( OUTER_VAR , INNER_VAR ,
* INDEX_VAR ) until we find a real Var or some kind of non - Var node ; then ,
* invoke the callback provided .
*/
static void
resolve_special_varno ( Node * node , deparse_context * context , void * private ,
void ( * callback ) ( Node * , deparse_context * , void * ) )
{
Var * var ;
deparse_namespace * dpns ;
/* If it's not a Var, invoke the callback. */
if ( ! IsA ( node , Var ) )
{
callback ( node , context , private ) ;
return ;
}
/* Find appropriate nesting depth */
var = ( Var * ) node ;
dpns = ( deparse_namespace * ) list_nth ( context - > namespaces ,
var - > varlevelsup ) ;
/*
* It ' s a special RTE , so recurse .
*/
if ( var - > varno = = OUTER_VAR & & dpns - > outer_tlist )
{
TargetEntry * tle ;
deparse_namespace save_dpns ;
tle = get_tle_by_resno ( dpns - > outer_tlist , var - > varattno ) ;
if ( ! tle )
elog ( ERROR , " bogus varattno for OUTER_VAR var: %d " , var - > varattno ) ;
push_child_plan ( dpns , dpns - > outer_planstate , & save_dpns ) ;
resolve_special_varno ( ( Node * ) tle - > expr , context , private , callback ) ;
pop_child_plan ( dpns , & save_dpns ) ;
return ;
}
else if ( var - > varno = = INNER_VAR & & dpns - > inner_tlist )
{
TargetEntry * tle ;
deparse_namespace save_dpns ;
tle = get_tle_by_resno ( dpns - > inner_tlist , var - > varattno ) ;
if ( ! tle )
elog ( ERROR , " bogus varattno for INNER_VAR var: %d " , var - > varattno ) ;
push_child_plan ( dpns , dpns - > inner_planstate , & save_dpns ) ;
resolve_special_varno ( ( Node * ) tle - > expr , context , private , callback ) ;
pop_child_plan ( dpns , & save_dpns ) ;
return ;
}
else if ( var - > varno = = INDEX_VAR & & dpns - > index_tlist )
{
TargetEntry * tle ;
tle = get_tle_by_resno ( dpns - > index_tlist , var - > varattno ) ;
if ( ! tle )
elog ( ERROR , " bogus varattno for INDEX_VAR var: %d " , var - > varattno ) ;
resolve_special_varno ( ( Node * ) tle - > expr , context , private , callback ) ;
return ;
}
else if ( var - > varno < 1 | | var - > varno > list_length ( dpns - > rtable ) )
elog ( ERROR , " bogus varno: %d " , var - > varno ) ;
/* Not special. Just invoke the callback. */
callback ( node , context , private ) ;
}
/*
* Get the name of a field of an expression of composite type . The
@ -7080,7 +7111,7 @@ get_rule_expr(Node *node, deparse_context *context,
break ;
case T_Aggref :
get_agg_expr ( ( Aggref * ) node , context ) ;
get_agg_expr ( ( Aggref * ) node , context , ( Aggref * ) node ) ;
break ;
case T_GroupingFunc :
@ -8236,13 +8267,36 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
* get_agg_expr - Parse back an Aggref node
*/
static void
get_agg_expr ( Aggref * aggref , deparse_context * context )
get_agg_expr ( Aggref * aggref , deparse_context * context ,
Aggref * original_aggref )
{
StringInfo buf = context - > buf ;
Oid argtypes [ FUNC_MAX_ARGS ] ;
int nargs ;
bool use_variadic ;
/*
* For a combining aggregate , we look up and deparse the corresponding
* partial aggregate instead . This is necessary because our input
* argument list has been replaced ; the new argument list always has just
* one element , which will point to a partial Aggref that supplies us with
* transition states to combine .
*/
if ( aggref - > aggcombine )
{
TargetEntry * tle = linitial ( aggref - > args ) ;
Assert ( list_length ( aggref - > args ) = = 1 ) ;
Assert ( IsA ( tle , TargetEntry ) ) ;
resolve_special_varno ( ( Node * ) tle - > expr , context , original_aggref ,
get_agg_combine_expr ) ;
return ;
}
/* Mark as PARTIAL, if appropriate. */
if ( original_aggref - > aggpartial )
appendStringInfoString ( buf , " PARTIAL " ) ;
/* Extract the argument types as seen by the parser */
nargs = get_aggregate_argtypes ( aggref , argtypes ) ;
@ -8311,6 +8365,24 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
appendStringInfoChar ( buf , ' ) ' ) ;
}
/*
* This is a helper function for get_agg_expr ( ) . It ' s used when we deparse
* a combining Aggref ; resolve_special_varno locates the corresponding partial
* Aggref and then calls this .
*/
static void
get_agg_combine_expr ( Node * node , deparse_context * context , void * private )
{
Aggref * aggref ;
Aggref * original_aggref = private ;
if ( ! IsA ( node , Aggref ) )
elog ( ERROR , " combining Aggref does not point to an Aggref " ) ;
aggref = ( Aggref * ) node ;
get_agg_expr ( aggref , context , original_aggref ) ;
}
/*
* get_windowfunc_expr - Parse back a WindowFunc node
*/