@@ -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 ,
@@ -3892,15 +3892,21 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
3892
3892
3893
3893
3894
3894
/*
3895
- * Get the name of a field of an expression of composite type.
3896
- *
3897
- * This is fairly straightforward except for the case of a Var of type RECORD.
3898
- * Since no actual table or view column is allowed to have type RECORD, such
3899
- * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
3900
- * drill down to find the ultimate defining expression and attempt to infer
3901
- * the field name from it. We ereport if we can't determine the name.
3895
+ * Get the name of a field of an expression of composite type. The
3896
+ * expression is usually a Var, but we handle other cases too.
3902
3897
*
3903
3898
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
3899
+ *
3900
+ * This is fairly straightforward when the expression has a named composite
3901
+ * type; we need only look up the type in the catalogs. However, the type
3902
+ * could also be RECORD. Since no actual table or view column is allowed to
3903
+ * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE
3904
+ * or to a subquery output. We drill down to find the ultimate defining
3905
+ * expression and attempt to infer the field name from it. We ereport if we
3906
+ * can't determine the name.
3907
+ *
3908
+ * Similarly, a PARAM of type RECORD has to refer to some expression of
3909
+ * a determinable composite type.
3904
3910
*/
3905
3911
static const char *
3906
3912
get_name_for_var_field (Var * var , int fieldno ,
@@ -3925,6 +3931,29 @@ get_name_for_var_field(Var *var, int fieldno,
3925
3931
return strVal (list_nth (r -> colnames , fieldno - 1 ));
3926
3932
}
3927
3933
3934
+ /*
3935
+ * If it's a Param of type RECORD, try to find what the Param refers to.
3936
+ */
3937
+ if (IsA (var , Param ))
3938
+ {
3939
+ Param * param = (Param * ) var ;
3940
+ ListCell * ancestor_cell ;
3941
+
3942
+ expr = find_param_referent (param , context , & dpns , & ancestor_cell );
3943
+ if (expr )
3944
+ {
3945
+ /* Found a match, so recurse to decipher the field name */
3946
+ deparse_namespace save_dpns ;
3947
+ const char * result ;
3948
+
3949
+ push_ancestor_plan (dpns , ancestor_cell , & save_dpns );
3950
+ result = get_name_for_var_field ((Var * ) expr , fieldno ,
3951
+ 0 , context );
3952
+ pop_ancestor_plan (dpns , & save_dpns );
3953
+ return result ;
3954
+ }
3955
+ }
3956
+
3928
3957
/*
3929
3958
* If it's a Var of type RECORD, we have to find what the Var refers to;
3930
3959
* if not, we can use get_expr_result_type. If that fails, we try
@@ -4279,17 +4308,25 @@ find_rte_by_refname(const char *refname, deparse_context *context)
4279
4308
}
4280
4309
4281
4310
/*
4282
- * Display a Param appropriately.
4311
+ * Try to find the referenced expression for a PARAM_EXEC Param that might
4312
+ * reference a parameter supplied by an upper NestLoop or SubPlan plan node.
4313
+ *
4314
+ * If successful, return the expression and set *dpns_p and *ancestor_cell_p
4315
+ * appropriately for calling push_ancestor_plan(). If no referent can be
4316
+ * found, return NULL.
4283
4317
*/
4284
- static void
4285
- get_parameter (Param * param , deparse_context * context )
4318
+ static Node *
4319
+ find_param_referent (Param * param , deparse_context * context ,
4320
+ deparse_namespace * * dpns_p , ListCell * * ancestor_cell_p )
4286
4321
{
4322
+ /* Initialize output parameters to prevent compiler warnings */
4323
+ * dpns_p = NULL ;
4324
+ * ancestor_cell_p = NULL ;
4325
+
4287
4326
/*
4288
- * If it's a PARAM_EXEC parameter, try to locate the expression from which
4289
- * the parameter was computed. This will necessarily be in some ancestor
4290
- * of the current expression's PlanState. Note that failing to find a
4291
- * referent isn't an error, since the Param might well be a subplan output
4292
- * rather than an input.
4327
+ * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
4328
+ * SubPlan argument. This will necessarily be in some ancestor of the
4329
+ * current expression's PlanState.
4293
4330
*/
4294
4331
if (param -> paramkind == PARAM_EXEC )
4295
4332
{
@@ -4324,10 +4361,10 @@ get_parameter(Param *param, deparse_context *context)
4324
4361
4325
4362
if (nlp -> paramno == param -> paramid )
4326
4363
{
4327
- /* Found a match, so print it */
4328
- print_parameter_expr (( Node * ) nlp -> paramval , lc ,
4329
- dpns , context ) ;
4330
- return ;
4364
+ /* Found a match, so return it */
4365
+ * dpns_p = dpns ;
4366
+ * ancestor_cell_p = lc ;
4367
+ return ( Node * ) nlp -> paramval ;
4331
4368
}
4332
4369
}
4333
4370
}
@@ -4353,9 +4390,10 @@ get_parameter(Param *param, deparse_context *context)
4353
4390
4354
4391
if (paramid == param -> paramid )
4355
4392
{
4356
- /* Found a match, so print it */
4357
- print_parameter_expr (arg , lc , dpns , context );
4358
- return ;
4393
+ /* Found a match, so return it */
4394
+ * dpns_p = dpns ;
4395
+ * ancestor_cell_p = lc ;
4396
+ return arg ;
4359
4397
}
4360
4398
}
4361
4399
@@ -4390,50 +4428,71 @@ get_parameter(Param *param, deparse_context *context)
4390
4428
}
4391
4429
}
4392
4430
4393
- /*
4394
- * Not PARAM_EXEC, or couldn't find referent: just print $N.
4395
- */
4396
- appendStringInfo (context -> buf , "$%d" , param -> paramid );
4431
+ /* No referent found */
4432
+ return NULL ;
4397
4433
}
4398
4434
4399
- /* Print a parameter reference expression found by get_parameter */
4435
+ /*
4436
+ * Display a Param appropriately.
4437
+ */
4400
4438
static void
4401
- print_parameter_expr (Node * expr , ListCell * ancestor_cell ,
4402
- deparse_namespace * dpns , deparse_context * context )
4439
+ get_parameter (Param * param , deparse_context * context )
4403
4440
{
4404
- deparse_namespace save_dpns ;
4405
- bool save_varprefix ;
4406
- bool need_paren ;
4407
-
4408
- /* Switch attention to the ancestor plan node */
4409
- push_ancestor_plan (dpns , ancestor_cell , & save_dpns );
4441
+ Node * expr ;
4442
+ deparse_namespace * dpns ;
4443
+ ListCell * ancestor_cell ;
4410
4444
4411
4445
/*
4412
- * Force prefixing of Vars, since they won't belong to the relation being
4413
- * scanned in the original plan node.
4446
+ * If it's a PARAM_EXEC parameter, try to locate the expression from which
4447
+ * the parameter was computed. Note that failing to find a referent isn't
4448
+ * an error, since the Param might well be a subplan output rather than an
4449
+ * input.
4414
4450
*/
4415
- save_varprefix = context -> varprefix ;
4416
- context -> varprefix = true;
4451
+ expr = find_param_referent (param , context , & dpns , & ancestor_cell );
4452
+ if (expr )
4453
+ {
4454
+ /* Found a match, so print it */
4455
+ deparse_namespace save_dpns ;
4456
+ bool save_varprefix ;
4457
+ bool need_paren ;
4417
4458
4418
- /*
4419
- * A Param's expansion is typically a Var, Aggref, or upper-level Param,
4420
- * which wouldn't need extra parentheses. Otherwise, insert parens to
4421
- * ensure the expression looks atomic.
4422
- */
4423
- need_paren = !(IsA (expr , Var ) ||
4424
- IsA (expr , Aggref ) ||
4425
- IsA (expr , Param ));
4426
- if (need_paren )
4427
- appendStringInfoChar (context -> buf , '(' );
4459
+ /* Switch attention to the ancestor plan node */
4460
+ push_ancestor_plan (dpns , ancestor_cell , & save_dpns );
4428
4461
4429
- get_rule_expr (expr , context , false);
4462
+ /*
4463
+ * Force prefixing of Vars, since they won't belong to the relation
4464
+ * being scanned in the original plan node.
4465
+ */
4466
+ save_varprefix = context -> varprefix ;
4467
+ context -> varprefix = true;
4430
4468
4431
- if (need_paren )
4432
- appendStringInfoChar (context -> buf , ')' );
4469
+ /*
4470
+ * A Param's expansion is typically a Var, Aggref, or upper-level
4471
+ * Param, which wouldn't need extra parentheses. Otherwise, insert
4472
+ * parens to ensure the expression looks atomic.
4473
+ */
4474
+ need_paren = !(IsA (expr , Var ) ||
4475
+ IsA (expr , Aggref ) ||
4476
+ IsA (expr , Param ));
4477
+ if (need_paren )
4478
+ appendStringInfoChar (context -> buf , '(' );
4479
+
4480
+ get_rule_expr (expr , context , false);
4481
+
4482
+ if (need_paren )
4483
+ appendStringInfoChar (context -> buf , ')' );
4484
+
4485
+ context -> varprefix = save_varprefix ;
4433
4486
4434
- context -> varprefix = save_varprefix ;
4487
+ pop_ancestor_plan ( dpns , & save_dpns ) ;
4435
4488
4436
- pop_ancestor_plan (dpns , & save_dpns );
4489
+ return ;
4490
+ }
4491
+
4492
+ /*
4493
+ * Not PARAM_EXEC, or couldn't find referent: just print $N.
4494
+ */
4495
+ appendStringInfo (context -> buf , "$%d" , param -> paramid );
4437
4496
}
4438
4497
4439
4498
/*
0 commit comments