@@ -207,9 +207,9 @@ static char *get_variable(Var *var, int levelsup, bool showstar,
207
207
deparse_context * context );
208
208
static RangeTblEntry * find_rte_by_refname (const char * refname ,
209
209
deparse_context * context );
210
+ static Node * find_param_referent (Param * param , deparse_context * context ,
211
+ deparse_namespace * * dpns_p , ListCell * * ancestor_cell_p );
210
212
static 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 );
213
213
static const char * get_simple_binary_op_name (OpExpr * expr );
214
214
static bool isSimpleNode (Node * node , Node * parentNode , int prettyFlags );
215
215
static void appendContextKeyword (deparse_context * context , const char * str ,
@@ -3889,15 +3889,21 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3889
3889
3890
3890
3891
3891
/*
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.
3899
3894
*
3900
3895
* 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.
3901
3907
*/
3902
3908
static const char *
3903
3909
get_name_for_var_field (Var * var , int fieldno ,
@@ -3922,6 +3928,29 @@ get_name_for_var_field(Var *var, int fieldno,
3922
3928
return strVal (list_nth (r -> colnames , fieldno - 1 ));
3923
3929
}
3924
3930
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
+
3925
3954
/*
3926
3955
* If it's a Var of type RECORD, we have to find what the Var refers to;
3927
3956
* 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)
4276
4305
}
4277
4306
4278
4307
/*
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.
4280
4314
*/
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 )
4283
4318
{
4319
+ /* Initialize output parameters to prevent compiler warnings */
4320
+ * dpns_p = NULL ;
4321
+ * ancestor_cell_p = NULL ;
4322
+
4284
4323
/*
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.
4290
4327
*/
4291
4328
if (param -> paramkind == PARAM_EXEC )
4292
4329
{
@@ -4321,10 +4358,10 @@ get_parameter(Param *param, deparse_context *context)
4321
4358
4322
4359
if (nlp -> paramno == param -> paramid )
4323
4360
{
4324
- /* Found a match, so print it */
4325
- print_parameter_expr (( Node * ) nlp -> paramval , lc ,
4326
- dpns , context ) ;
4327
- return ;
4361
+ /* Found a match, so return it */
4362
+ * dpns_p = dpns ;
4363
+ * ancestor_cell_p = lc ;
4364
+ return ( Node * ) nlp -> paramval ;
4328
4365
}
4329
4366
}
4330
4367
}
@@ -4350,9 +4387,10 @@ get_parameter(Param *param, deparse_context *context)
4350
4387
4351
4388
if (paramid == param -> paramid )
4352
4389
{
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 ;
4356
4394
}
4357
4395
}
4358
4396
@@ -4387,50 +4425,71 @@ get_parameter(Param *param, deparse_context *context)
4387
4425
}
4388
4426
}
4389
4427
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 ;
4394
4430
}
4395
4431
4396
- /* Print a parameter reference expression found by get_parameter */
4432
+ /*
4433
+ * Display a Param appropriately.
4434
+ */
4397
4435
static 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 )
4400
4437
{
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 ;
4407
4441
4408
4442
/*
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.
4411
4447
*/
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 ;
4414
4455
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 );
4425
4458
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;
4427
4465
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 ;
4430
4483
4431
- context -> varprefix = save_varprefix ;
4484
+ pop_ancestor_plan ( dpns , & save_dpns ) ;
4432
4485
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 );
4434
4493
}
4435
4494
4436
4495
/*
0 commit comments