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

Commit6867f96

Browse files
committed
Make pg_get_expr() more bulletproof.
Since this function is defined to accept pg_node_tree values, it couldget applied to any nodetree that can appear in a cataloged pg_node_treecolumn. Some such cases can't be supported --- for example, its APIdoesn't allow providing referents for more than one relation --- butwe should try to throw a user-facing error rather than an internalerror when encountering such a case.In support of this, extend expression_tree_walker/mutator to be surethey'll work on any such node tree (which basically means addingsupport for relpartbound node types). That allows us to run pull_varnosand check for the case of multiple relations before we start processingthe tree. The alternative of changing the low-level error thrown for anout-of-range varno isn't appealing, because that could mask actual bugsin other usages of ruleutils.Per report from Justin Pryzby. This is basically cosmetic, so noback-patch.Discussion:https://postgr.es/m/20211219205422.GT17618@telsasoft.com
1 parent96a6f11 commit6867f96

File tree

3 files changed

+94
-3
lines changed

3 files changed

+94
-3
lines changed

‎src/backend/nodes/nodeFuncs.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,6 +2201,26 @@ expression_tree_walker(Node *node,
22012201
return true;
22022202
}
22032203
break;
2204+
caseT_PartitionBoundSpec:
2205+
{
2206+
PartitionBoundSpec*pbs= (PartitionBoundSpec*)node;
2207+
2208+
if (walker(pbs->listdatums,context))
2209+
return true;
2210+
if (walker(pbs->lowerdatums,context))
2211+
return true;
2212+
if (walker(pbs->upperdatums,context))
2213+
return true;
2214+
}
2215+
break;
2216+
caseT_PartitionRangeDatum:
2217+
{
2218+
PartitionRangeDatum*prd= (PartitionRangeDatum*)node;
2219+
2220+
if (walker(prd->value,context))
2221+
return true;
2222+
}
2223+
break;
22042224
caseT_List:
22052225
foreach(temp, (List*)node)
22062226
{
@@ -3092,6 +3112,28 @@ expression_tree_mutator(Node *node,
30923112
return (Node*)newnode;
30933113
}
30943114
break;
3115+
caseT_PartitionBoundSpec:
3116+
{
3117+
PartitionBoundSpec*pbs= (PartitionBoundSpec*)node;
3118+
PartitionBoundSpec*newnode;
3119+
3120+
FLATCOPY(newnode,pbs,PartitionBoundSpec);
3121+
MUTATE(newnode->listdatums,pbs->listdatums,List*);
3122+
MUTATE(newnode->lowerdatums,pbs->lowerdatums,List*);
3123+
MUTATE(newnode->upperdatums,pbs->upperdatums,List*);
3124+
return (Node*)newnode;
3125+
}
3126+
break;
3127+
caseT_PartitionRangeDatum:
3128+
{
3129+
PartitionRangeDatum*prd= (PartitionRangeDatum*)node;
3130+
PartitionRangeDatum*newnode;
3131+
3132+
FLATCOPY(newnode,prd,PartitionRangeDatum);
3133+
MUTATE(newnode->value,prd->value,Node*);
3134+
return (Node*)newnode;
3135+
}
3136+
break;
30953137
caseT_List:
30963138
{
30973139
/*

‎src/backend/optimizer/util/var.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ static Relids alias_relid_set(Query *query, Relids relids);
8888
*Create a set of all the distinct varnos present in a parsetree.
8989
*Only varnos that reference level-zero rtable entries are considered.
9090
*
91+
* "root" can be passed as NULL if it is not necessary to process
92+
* PlaceHolderVars.
93+
*
9194
* NOTE: this is used on not-yet-planned expressions. It may therefore find
9295
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
9396
* references to the desired rtable level!But when we find a completed
@@ -168,9 +171,13 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
168171
/*
169172
* If a PlaceHolderVar is not of the target query level, ignore it,
170173
* instead recursing into its expression to see if it contains any
171-
* vars that are of the target level.
174+
* vars that are of the target level. We'll also do that when the
175+
* caller doesn't pass a "root" pointer. (We probably shouldn't see
176+
* PlaceHolderVars at all in such cases, but if we do, this is a
177+
* reasonable behavior.)
172178
*/
173-
if (phv->phlevelsup==context->sublevels_up)
179+
if (phv->phlevelsup==context->sublevels_up&&
180+
context->root!=NULL)
174181
{
175182
/*
176183
* Ideally, the PHV's contribution to context->varnos is its

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

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2561,6 +2561,12 @@ decompile_column_index_array(Datum column_index_array, Oid relId,
25612561
* the one specified by the second parameter. This is sufficient for
25622562
* partial indexes, column default expressions, etc. We also support
25632563
* Var-free expressions, for which the OID can be InvalidOid.
2564+
*
2565+
* We expect this function to work, or throw a reasonably clean error,
2566+
* for any node tree that can appear in a catalog pg_node_tree column.
2567+
* Query trees, such as those appearing in pg_rewrite.ev_action, are
2568+
* not supported. Nor are expressions in more than one relation, which
2569+
* can appear in places like pg_rewrite.ev_qual.
25642570
* ----------
25652571
*/
25662572
Datum
@@ -2622,18 +2628,54 @@ static text *
26222628
pg_get_expr_worker(text*expr,Oidrelid,constchar*relname,intprettyFlags)
26232629
{
26242630
Node*node;
2631+
Node*tst;
2632+
Relidsrelids;
26252633
List*context;
26262634
char*exprstr;
26272635
char*str;
26282636

2629-
/* Convert input TEXT object to C string */
2637+
/* Convert inputpg_node_tree (reallyTEXT) object to C string */
26302638
exprstr=text_to_cstring(expr);
26312639

26322640
/* Convert expression to node tree */
26332641
node= (Node*)stringToNode(exprstr);
26342642

26352643
pfree(exprstr);
26362644

2645+
/*
2646+
* Throw error if the input is a querytree rather than an expression tree.
2647+
* While we could support queries here, there seems no very good reason
2648+
* to. In most such catalog columns, we'll see a List of Query nodes, or
2649+
* even nested Lists, so drill down to a non-List node before checking.
2650+
*/
2651+
tst=node;
2652+
while (tst&&IsA(tst,List))
2653+
tst=linitial((List*)tst);
2654+
if (tst&&IsA(tst,Query))
2655+
ereport(ERROR,
2656+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2657+
errmsg("input is a query, not an expression")));
2658+
2659+
/*
2660+
* Throw error if the expression contains Vars we won't be able to
2661+
* deparse.
2662+
*/
2663+
relids=pull_varnos(NULL,node);
2664+
if (OidIsValid(relid))
2665+
{
2666+
if (!bms_is_subset(relids,bms_make_singleton(1)))
2667+
ereport(ERROR,
2668+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2669+
errmsg("expression contains variables of more than one relation")));
2670+
}
2671+
else
2672+
{
2673+
if (!bms_is_empty(relids))
2674+
ereport(ERROR,
2675+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2676+
errmsg("expression contains variables")));
2677+
}
2678+
26372679
/* Prepare deparse context if needed */
26382680
if (OidIsValid(relid))
26392681
context=deparse_context_for(relname,relid);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp