@@ -207,9 +207,9 @@ static char *get_variable(Var *var, int levelsup, bool showstar,
207207deparse_context * context );
208208static RangeTblEntry * find_rte_by_refname (const char * refname ,
209209deparse_context * context );
210+ static Node * find_param_referent (Param * param ,deparse_context * context ,
211+ deparse_namespace * * dpns_p ,ListCell * * ancestor_cell_p );
210212static void get_parameter (Param * param ,deparse_context * context );
211- static void print_parameter_expr (Node * expr ,ListCell * ancestor_cell ,
212- deparse_namespace * dpns ,deparse_context * context );
213213static const char * get_simple_binary_op_name (OpExpr * expr );
214214static bool isSimpleNode (Node * node ,Node * parentNode ,int prettyFlags );
215215static void appendContextKeyword (deparse_context * context ,const char * str ,
@@ -3889,15 +3889,21 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
38893889
38903890
38913891/*
3892- * Get the name of a field of an expression of composite type.
3893- *
3894- * This is fairly straightforward except for the case of a Var of type RECORD.
3895- * Since no actual table or view column is allowed to have type RECORD, such
3896- * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output.We
3897- * drill down to find the ultimate defining expression and attempt to infer
3898- * the field name from it.We ereport if we can't determine the name.
3892+ * Get the name of a field of an expression of composite type. The
3893+ * expression is usually a Var, but we handle other cases too.
38993894 *
39003895 * levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3896+ *
3897+ * This is fairly straightforward when the expression has a named composite
3898+ * type; we need only look up the type in the catalogs. However, the type
3899+ * could also be RECORD. Since no actual table or view column is allowed to
3900+ * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
3901+ * or to a subquery output. We drill down to find the ultimate defining
3902+ * expression and attempt to infer the field name from it. We ereport if we
3903+ * can't determine the name.
3904+ *
3905+ * Similarly, a PARAM of type RECORD has to refer to some expression of
3906+ * a determinable composite type.
39013907 */
39023908static const char *
39033909get_name_for_var_field (Var * var ,int fieldno ,
@@ -3922,6 +3928,29 @@ get_name_for_var_field(Var *var, int fieldno,
39223928return strVal (list_nth (r -> colnames ,fieldno - 1 ));
39233929}
39243930
3931+ /*
3932+ * If it's a Param of type RECORD, try to find what the Param refers to.
3933+ */
3934+ if (IsA (var ,Param ))
3935+ {
3936+ Param * param = (Param * )var ;
3937+ ListCell * ancestor_cell ;
3938+
3939+ expr = find_param_referent (param ,context ,& dpns ,& ancestor_cell );
3940+ if (expr )
3941+ {
3942+ /* Found a match, so recurse to decipher the field name */
3943+ deparse_namespace save_dpns ;
3944+ const char * result ;
3945+
3946+ push_ancestor_plan (dpns ,ancestor_cell ,& save_dpns );
3947+ result = get_name_for_var_field ((Var * )expr ,fieldno ,
3948+ 0 ,context );
3949+ pop_ancestor_plan (dpns ,& save_dpns );
3950+ return result ;
3951+ }
3952+ }
3953+
39253954/*
39263955 * If it's a Var of type RECORD, we have to find what the Var refers to;
39273956 * if not, we can use get_expr_result_type. If that fails, we try
@@ -4276,17 +4305,25 @@ find_rte_by_refname(const char *refname, deparse_context *context)
42764305}
42774306
42784307/*
4279- * Display a Param appropriately.
4308+ * Try to find the referenced expression for a PARAM_EXEC Param that might
4309+ * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
4310+ *
4311+ * If successful, return the expression and set *dpns_p and *ancestor_cell_p
4312+ * appropriately for calling push_ancestor_plan(). If no referent can be
4313+ * found, return NULL.
42804314 */
4281- static void
4282- get_parameter (Param * param ,deparse_context * context )
4315+ static Node *
4316+ find_param_referent (Param * param ,deparse_context * context ,
4317+ deparse_namespace * * dpns_p ,ListCell * * ancestor_cell_p )
42834318{
4319+ /* Initialize output parameters to prevent compiler warnings */
4320+ * dpns_p = NULL ;
4321+ * ancestor_cell_p = NULL ;
4322+
42844323/*
4285- * If it's a PARAM_EXEC parameter, try to locate the expression from which
4286- * the parameter was computed.This will necessarily be in some ancestor
4287- * of the current expression's PlanState. Note that failing to find a
4288- * referent isn't an error, since the Param might well be a subplan output
4289- * rather than an input.
4324+ * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
4325+ * SubPlan argument. This will necessarily be in some ancestor of the
4326+ * current expression's PlanState.
42904327 */
42914328if (param -> paramkind == PARAM_EXEC )
42924329{
@@ -4321,10 +4358,10 @@ get_parameter(Param *param, deparse_context *context)
43214358
43224359if (nlp -> paramno == param -> paramid )
43234360{
4324- /* Found a match, soprint it */
4325- print_parameter_expr (( Node * ) nlp -> paramval , lc ,
4326- dpns , context ) ;
4327- return ;
4361+ /* Found a match, soreturn it */
4362+ * dpns_p = dpns ;
4363+ * ancestor_cell_p = lc ;
4364+ return ( Node * ) nlp -> paramval ;
43284365}
43294366}
43304367}
@@ -4350,9 +4387,10 @@ get_parameter(Param *param, deparse_context *context)
43504387
43514388if (paramid == param -> paramid )
43524389{
4353- /* Found a match, so print it */
4354- print_parameter_expr (arg ,lc ,dpns ,context );
4355- return ;
4390+ /* Found a match, so return it */
4391+ * dpns_p = dpns ;
4392+ * ancestor_cell_p = lc ;
4393+ return arg ;
43564394}
43574395}
43584396
@@ -4387,50 +4425,71 @@ get_parameter(Param *param, deparse_context *context)
43874425}
43884426}
43894427
4390- /*
4391- * Not PARAM_EXEC, or couldn't find referent: just print $N.
4392- */
4393- appendStringInfo (context -> buf ,"$%d" ,param -> paramid );
4428+ /* No referent found */
4429+ return NULL ;
43944430}
43954431
4396- /* Print a parameter reference expression found by get_parameter */
4432+ /*
4433+ * Display a Param appropriately.
4434+ */
43974435static void
4398- print_parameter_expr (Node * expr ,ListCell * ancestor_cell ,
4399- deparse_namespace * dpns ,deparse_context * context )
4436+ get_parameter (Param * param ,deparse_context * context )
44004437{
4401- deparse_namespace save_dpns ;
4402- bool save_varprefix ;
4403- bool need_paren ;
4404-
4405- /* Switch attention to the ancestor plan node */
4406- push_ancestor_plan (dpns ,ancestor_cell ,& save_dpns );
4438+ Node * expr ;
4439+ deparse_namespace * dpns ;
4440+ ListCell * ancestor_cell ;
44074441
44084442/*
4409- * Force prefixing of Vars, since they won't belong to the relation being
4410- * scanned in the original plan node.
4443+ * If it's a PARAM_EXEC parameter, try to locate the expression from which
4444+ * the parameter was computed. Note that failing to find a referent isn't
4445+ * an error, since the Param might well be a subplan output rather than an
4446+ * input.
44114447 */
4412- save_varprefix = context -> varprefix ;
4413- context -> varprefix = true;
4448+ expr = find_param_referent (param ,context ,& dpns ,& ancestor_cell );
4449+ if (expr )
4450+ {
4451+ /* Found a match, so print it */
4452+ deparse_namespace save_dpns ;
4453+ bool save_varprefix ;
4454+ bool need_paren ;
44144455
4415- /*
4416- * A Param's expansion is typically a Var, Aggref, or upper-level Param,
4417- * which wouldn't need extra parentheses. Otherwise, insert parens to
4418- * ensure the expression looks atomic.
4419- */
4420- need_paren = !(IsA (expr ,Var )||
4421- IsA (expr ,Aggref )||
4422- IsA (expr ,Param ));
4423- if (need_paren )
4424- appendStringInfoChar (context -> buf ,'(' );
4456+ /* Switch attention to the ancestor plan node */
4457+ push_ancestor_plan (dpns ,ancestor_cell ,& save_dpns );
44254458
4426- get_rule_expr (expr ,context , false);
4459+ /*
4460+ * Force prefixing of Vars, since they won't belong to the relation
4461+ * being scanned in the original plan node.
4462+ */
4463+ save_varprefix = context -> varprefix ;
4464+ context -> varprefix = true;
44274465
4428- if (need_paren )
4429- appendStringInfoChar (context -> buf ,')' );
4466+ /*
4467+ * A Param's expansion is typically a Var, Aggref, or upper-level
4468+ * Param, which wouldn't need extra parentheses. Otherwise, insert
4469+ * parens to ensure the expression looks atomic.
4470+ */
4471+ need_paren = !(IsA (expr ,Var )||
4472+ IsA (expr ,Aggref )||
4473+ IsA (expr ,Param ));
4474+ if (need_paren )
4475+ appendStringInfoChar (context -> buf ,'(' );
4476+
4477+ get_rule_expr (expr ,context , false);
4478+
4479+ if (need_paren )
4480+ appendStringInfoChar (context -> buf ,')' );
4481+
4482+ context -> varprefix = save_varprefix ;
44304483
4431- context -> varprefix = save_varprefix ;
4484+ pop_ancestor_plan ( dpns , & save_dpns ) ;
44324485
4433- pop_ancestor_plan (dpns ,& save_dpns );
4486+ return ;
4487+ }
4488+
4489+ /*
4490+ * Not PARAM_EXEC, or couldn't find referent: just print $N.
4491+ */
4492+ appendStringInfo (context -> buf ,"$%d" ,param -> paramid );
44344493}
44354494
44364495/*