Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita7d9203

Browse files
committed
Fix get_name_for_var_field() to deal with RECORD Params.
With 9.1's use of Params to pass down values from NestLoop join nodesto their inner plans, it is possible for a Param to have type RECORD, inwhich case the set of fields comprising the value isn't determinable byinspection of the Param alone. However, just as with a Var of type RECORD,we can find out what we need to know if we can locate the expression thatthe Param represents. We already knew how to do this in get_parameter(),but I'd overlooked the need to be able to cope in get_name_for_var_field(),which led to EXPLAIN failing with "record type has not been registered".To fix, refactor the search code in get_parameter() so it can be used byboth functions.Per report from Marti Raudsepp.
1 parentf195937 commita7d9203

File tree

1 file changed

+115
-56
lines changed

1 file changed

+115
-56
lines changed

‎src/backend/utils/adt/ruleutils.c

Lines changed: 115 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ static char *get_variable(Var *var, int levelsup, bool showstar,
207207
deparse_context*context);
208208
staticRangeTblEntry*find_rte_by_refname(constchar*refname,
209209
deparse_context*context);
210+
staticNode*find_param_referent(Param*param,deparse_context*context,
211+
deparse_namespace**dpns_p,ListCell**ancestor_cell_p);
210212
staticvoidget_parameter(Param*param,deparse_context*context);
211-
staticvoidprint_parameter_expr(Node*expr,ListCell*ancestor_cell,
212-
deparse_namespace*dpns,deparse_context*context);
213213
staticconstchar*get_simple_binary_op_name(OpExpr*expr);
214214
staticboolisSimpleNode(Node*node,Node*parentNode,intprettyFlags);
215215
staticvoidappendContextKeyword(deparse_context*context,constchar*str,
@@ -3892,15 +3892,21 @@ get_variable(Var *var, int levelsup, bool showstar, deparse_context *context)
38923892

38933893

38943894
/*
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.
39023897
*
39033898
* 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.
39043910
*/
39053911
staticconstchar*
39063912
get_name_for_var_field(Var*var,intfieldno,
@@ -3925,6 +3931,29 @@ get_name_for_var_field(Var *var, int fieldno,
39253931
returnstrVal(list_nth(r->colnames,fieldno-1));
39263932
}
39273933

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_namespacesave_dpns;
3947+
constchar*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+
returnresult;
3954+
}
3955+
}
3956+
39283957
/*
39293958
* If it's a Var of type RECORD, we have to find what the Var refers to;
39303959
* 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)
42794308
}
42804309

42814310
/*
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.
42834317
*/
4284-
staticvoid
4285-
get_parameter(Param*param,deparse_context*context)
4318+
staticNode*
4319+
find_param_referent(Param*param,deparse_context*context,
4320+
deparse_namespace**dpns_p,ListCell**ancestor_cell_p)
42864321
{
4322+
/* Initialize output parameters to prevent compiler warnings */
4323+
*dpns_p=NULL;
4324+
*ancestor_cell_p=NULL;
4325+
42874326
/*
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.
42934330
*/
42944331
if (param->paramkind==PARAM_EXEC)
42954332
{
@@ -4324,10 +4361,10 @@ get_parameter(Param *param, deparse_context *context)
43244361

43254362
if (nlp->paramno==param->paramid)
43264363
{
4327-
/* Found a match, soprint it */
4328-
print_parameter_expr((Node*)nlp->paramval,lc,
4329-
dpns,context);
4330-
return;
4364+
/* Found a match, soreturn it */
4365+
*dpns_p=dpns;
4366+
*ancestor_cell_p=lc;
4367+
return (Node*)nlp->paramval;
43314368
}
43324369
}
43334370
}
@@ -4353,9 +4390,10 @@ get_parameter(Param *param, deparse_context *context)
43534390

43544391
if (paramid==param->paramid)
43554392
{
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+
returnarg;
43594397
}
43604398
}
43614399

@@ -4390,50 +4428,71 @@ get_parameter(Param *param, deparse_context *context)
43904428
}
43914429
}
43924430

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+
returnNULL;
43974433
}
43984434

4399-
/* Print a parameter reference expression found by get_parameter */
4435+
/*
4436+
* Display a Param appropriately.
4437+
*/
44004438
staticvoid
4401-
print_parameter_expr(Node*expr,ListCell*ancestor_cell,
4402-
deparse_namespace*dpns,deparse_context*context)
4439+
get_parameter(Param*param,deparse_context*context)
44034440
{
4404-
deparse_namespacesave_dpns;
4405-
boolsave_varprefix;
4406-
boolneed_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;
44104444

44114445
/*
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.
44144450
*/
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_namespacesave_dpns;
4456+
boolsave_varprefix;
4457+
boolneed_paren;
44174458

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);
44284461

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;
44304468

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;
44334486

4434-
context->varprefix=save_varprefix;
4487+
pop_ancestor_plan(dpns,&save_dpns);
44354488

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);
44374496
}
44384497

44394498
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp