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

Commita44174c

Browse files
committed
Fix subselect.c to avoid assuming that a SubLink's testexpr references each
subquery output column exactly once left-to-right. Although this is the casein the original parser output, it might not be so after rewriting andconstant-folding, as illustrated by bug #3882 from Jan Mate. Insteadscan the subquery's target list to obtain needed per-column information;this is duplicative of what the parser did, but only a couple dozen linesneed be copied, and we can clean up a couple of notational uglinesses.Bug was introduced in 8.2 as part of revision of SubLink representation.
1 parent0df7717 commita44174c

File tree

1 file changed

+107
-70
lines changed

1 file changed

+107
-70
lines changed

‎src/backend/optimizer/plan/subselect.c

Lines changed: 107 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.128 2008/01/01 19:45:50 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.129 2008/01/17 20:35:27 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -35,8 +35,7 @@
3535
typedefstructconvert_testexpr_context
3636
{
3737
PlannerInfo*root;
38-
intrtindex;/* RT index for Vars, or 0 for Params */
39-
List*righthandIds;/* accumulated list of Vars or Param IDs */
38+
List*subst_nodes;/* Nodes to substitute for Params */
4039
}convert_testexpr_context;
4140

4241
typedefstructprocess_sublinks_context
@@ -53,10 +52,13 @@ typedef struct finalize_primnode_context
5352
}finalize_primnode_context;
5453

5554

55+
staticList*generate_subquery_params(PlannerInfo*root,List*tlist,
56+
List**paramIds);
57+
staticList*generate_subquery_vars(PlannerInfo*root,List*tlist,
58+
Indexvarno);
5659
staticNode*convert_testexpr(PlannerInfo*root,
5760
Node*testexpr,
58-
intrtindex,
59-
List**righthandIds);
61+
List*subst_nodes);
6062
staticNode*convert_testexpr_mutator(Node*node,
6163
convert_testexpr_context*context);
6264
staticboolsubplan_is_hashable(SubLink*slink,SubPlan*node,Plan*plan);
@@ -374,10 +376,14 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
374376
elseif (splan->parParam==NIL&&slink->subLinkType==ROWCOMPARE_SUBLINK)
375377
{
376378
/* Adjust the Params */
379+
List*params;
380+
381+
params=generate_subquery_params(root,
382+
plan->targetlist,
383+
&splan->paramIds);
377384
result=convert_testexpr(root,
378385
testexpr,
379-
0,
380-
&splan->paramIds);
386+
params);
381387
splan->setParam=list_copy(splan->paramIds);
382388
isInitPlan= true;
383389

@@ -388,14 +394,17 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
388394
}
389395
else
390396
{
397+
List*params;
391398
List*args;
392399
ListCell*l;
393400

394401
/* Adjust the Params */
402+
params=generate_subquery_params(root,
403+
plan->targetlist,
404+
&splan->paramIds);
395405
splan->testexpr=convert_testexpr(root,
396406
testexpr,
397-
0,
398-
&splan->paramIds);
407+
params);
399408

400409
/*
401410
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
@@ -482,17 +491,76 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
482491
returnresult;
483492
}
484493

494+
/*
495+
* generate_subquery_params: build a list of Params representing the output
496+
* columns of a sublink's sub-select, given the sub-select's targetlist.
497+
*
498+
* We also return an integer list of the paramids of the Params.
499+
*/
500+
staticList*
501+
generate_subquery_params(PlannerInfo*root,List*tlist,List**paramIds)
502+
{
503+
List*result;
504+
List*ids;
505+
ListCell*lc;
506+
507+
result=ids=NIL;
508+
foreach(lc,tlist)
509+
{
510+
TargetEntry*tent= (TargetEntry*)lfirst(lc);
511+
Param*param;
512+
513+
if (tent->resjunk)
514+
continue;
515+
516+
param=generate_new_param(root,
517+
exprType((Node*)tent->expr),
518+
exprTypmod((Node*)tent->expr));
519+
result=lappend(result,param);
520+
ids=lappend_int(ids,param->paramid);
521+
}
522+
523+
*paramIds=ids;
524+
returnresult;
525+
}
526+
527+
/*
528+
* generate_subquery_vars: build a list of Vars representing the output
529+
* columns of a sublink's sub-select, given the sub-select's targetlist.
530+
* The Vars have the specified varno (RTE index).
531+
*/
532+
staticList*
533+
generate_subquery_vars(PlannerInfo*root,List*tlist,Indexvarno)
534+
{
535+
List*result;
536+
ListCell*lc;
537+
538+
result=NIL;
539+
foreach(lc,tlist)
540+
{
541+
TargetEntry*tent= (TargetEntry*)lfirst(lc);
542+
Var*var;
543+
544+
if (tent->resjunk)
545+
continue;
546+
547+
var=makeVar(varno,
548+
tent->resno,
549+
exprType((Node*)tent->expr),
550+
exprTypmod((Node*)tent->expr),
551+
0);
552+
result=lappend(result,var);
553+
}
554+
555+
returnresult;
556+
}
557+
485558
/*
486559
* convert_testexpr: convert the testexpr given by the parser into
487560
* actually executable form. This entails replacing PARAM_SUBLINK Params
488-
* with Params or Vars representing the results of the sub-select:
489-
*
490-
* If rtindex is 0, we build Params to represent the sub-select outputs.
491-
* The paramids of the Params created are returned in the *righthandIds list.
492-
*
493-
* If rtindex is not 0, we build Vars using that rtindex as varno.Copies
494-
* of the Var nodes are returned in *righthandIds (this is a bit of a type
495-
* cheat, but we can get away with it).
561+
* with Params or Vars representing the results of the sub-select. The
562+
* nodes to be substituted are passed in as the List result from
563+
* generate_subquery_params or generate_subquery_vars.
496564
*
497565
* The given testexpr has already been recursively processed by
498566
* process_sublinks_mutator. Hence it can no longer contain any
@@ -502,18 +570,13 @@ make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
502570
staticNode*
503571
convert_testexpr(PlannerInfo*root,
504572
Node*testexpr,
505-
intrtindex,
506-
List**righthandIds)
573+
List*subst_nodes)
507574
{
508-
Node*result;
509575
convert_testexpr_contextcontext;
510576

511577
context.root=root;
512-
context.rtindex=rtindex;
513-
context.righthandIds=NIL;
514-
result=convert_testexpr_mutator(testexpr,&context);
515-
*righthandIds=context.righthandIds;
516-
returnresult;
578+
context.subst_nodes=subst_nodes;
579+
returnconvert_testexpr_mutator(testexpr,&context);
517580
}
518581

519582
staticNode*
@@ -528,47 +591,17 @@ convert_testexpr_mutator(Node *node,
528591

529592
if (param->paramkind==PARAM_SUBLINK)
530593
{
531-
/*
532-
* We expect to encounter the Params in column-number sequence. We
533-
* could handle non-sequential order if necessary, but for now
534-
* there's no need. (This is also a useful cross-check that we
535-
* aren't finding any unexpected Params.)
536-
*/
537-
if (param->paramid!=list_length(context->righthandIds)+1)
594+
if (param->paramid <=0||
595+
param->paramid>list_length(context->subst_nodes))
538596
elog(ERROR,"unexpected PARAM_SUBLINK ID: %d",param->paramid);
539597

540-
if (context->rtindex)
541-
{
542-
/* Make the Var node representing the subplan's result */
543-
Var*newvar;
544-
545-
newvar=makeVar(context->rtindex,
546-
param->paramid,
547-
param->paramtype,
548-
param->paramtypmod,
549-
0);
550-
551-
/*
552-
* Copy it for caller.NB: we need a copy to avoid having
553-
* doubly-linked substructure in the modified parse tree.
554-
*/
555-
context->righthandIds=lappend(context->righthandIds,
556-
copyObject(newvar));
557-
return (Node*)newvar;
558-
}
559-
else
560-
{
561-
/* Make the Param node representing the subplan's result */
562-
Param*newparam;
563-
564-
newparam=generate_new_param(context->root,
565-
param->paramtype,
566-
param->paramtypmod);
567-
/* Record its ID */
568-
context->righthandIds=lappend_int(context->righthandIds,
569-
newparam->paramid);
570-
return (Node*)newparam;
571-
}
598+
/*
599+
* We copy the list item to avoid having doubly-linked
600+
* substructure in the modified parse tree. This is probably
601+
* unnecessary when it's a Param, but be safe.
602+
*/
603+
return (Node*)copyObject(list_nth(context->subst_nodes,
604+
param->paramid-1));
572605
}
573606
}
574607
returnexpression_tree_mutator(node,
@@ -786,20 +819,24 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
786819
ininfo->in_operators=in_operators;
787820

788821
/*
789-
* Build the result qual expression. As a side effect,
790822
* ininfo->sub_targetlist is filled with a list of Vars representing the
791823
* subselect outputs.
792824
*/
793-
result=convert_testexpr(root,
794-
sublink->testexpr,
795-
rtindex,
796-
&ininfo->sub_targetlist);
797-
825+
ininfo->sub_targetlist=generate_subquery_vars(root,
826+
subselect->targetList,
827+
rtindex);
798828
Assert(list_length(in_operators)==list_length(ininfo->sub_targetlist));
799829

800830
/* Add the completed node to the query's list */
801831
root->in_info_list=lappend(root->in_info_list,ininfo);
802832

833+
/*
834+
* Build the result qual expression.
835+
*/
836+
result=convert_testexpr(root,
837+
sublink->testexpr,
838+
ininfo->sub_targetlist);
839+
803840
returnresult;
804841
}
805842

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp