Skip to content

Commit b307d7a

Browse files
committed
Fix planning of SubLinks to ensure that Vars generated from transformation of
a sublink's test expression have the correct vartypmod, rather than defaulting to -1. There's at least one place where this is important because we're expecting these Vars to be exactly equal() to those appearing in the subplan itself. This is a pretty klugy solution --- it would likely be cleaner to change Param nodes to include a typmod field --- but we can't do that in the already-released 8.2 branch. Per bug report from Hubert Fongarnand.
1 parent 886a02d commit b307d7a

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

src/backend/optimizer/plan/subselect.c

Lines changed: 31 additions & 7 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.112 2006/10/04 00:29:54 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.113 2006/12/06 19:40:01 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -75,6 +75,7 @@ typedef struct convert_testexpr_context
7575
{
7676
int rtindex; /* RT index for Vars, or 0 for Params */
7777
List *righthandIds; /* accumulated list of Vars or Param IDs */
78+
List *sub_tlist; /* subselect targetlist (if given) */
7879
} convert_testexpr_context;
7980

8081
typedef struct finalize_primnode_context
@@ -86,7 +87,8 @@ typedef struct finalize_primnode_context
8687

8788
static Node *convert_testexpr(Node *testexpr,
8889
int rtindex,
89-
List **righthandIds);
90+
List **righthandIds,
91+
List *sub_tlist);
9092
static Node *convert_testexpr_mutator(Node *node,
9193
convert_testexpr_context *context);
9294
static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
@@ -379,7 +381,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
379381
/* Adjust the Params */
380382
result = convert_testexpr(testexpr,
381383
0,
382-
&node->paramIds);
384+
&node->paramIds,
385+
NIL);
383386
node->setParam = list_copy(node->paramIds);
384387
PlannerInitPlan = lappend(PlannerInitPlan, node);
385388

@@ -396,7 +399,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
396399
/* Adjust the Params */
397400
node->testexpr = convert_testexpr(testexpr,
398401
0,
399-
&node->paramIds);
402+
&node->paramIds,
403+
NIL);
400404

401405
/*
402406
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
@@ -470,6 +474,10 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
470474
* of the Var nodes are returned in *righthandIds (this is a bit of a type
471475
* cheat, but we can get away with it).
472476
*
477+
* The subquery targetlist need be supplied only if rtindex is not 0.
478+
* We consult it to extract the correct typmods for the created Vars.
479+
* (XXX this is a kluge that could go away if Params carried typmod.)
480+
*
473481
* The given testexpr has already been recursively processed by
474482
* process_sublinks_mutator. Hence it can no longer contain any
475483
* PARAM_SUBLINK Params for lower SubLink nodes; we can safely assume that
@@ -478,13 +486,15 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
478486
static Node *
479487
convert_testexpr(Node *testexpr,
480488
int rtindex,
481-
List **righthandIds)
489+
List **righthandIds,
490+
List *sub_tlist)
482491
{
483492
Node *result;
484493
convert_testexpr_context context;
485494

486495
context.rtindex = rtindex;
487496
context.righthandIds = NIL;
497+
context.sub_tlist = sub_tlist;
488498
result = convert_testexpr_mutator(testexpr, &context);
489499
*righthandIds = context.righthandIds;
490500
return result;
@@ -516,10 +526,23 @@ convert_testexpr_mutator(Node *node,
516526
/* Make the Var node representing the subplan's result */
517527
Var *newvar;
518528

529+
/*
530+
* XXX kluge: since Params don't carry typmod, we have to
531+
* look into the subquery targetlist to find out the right
532+
* typmod to assign to the Var.
533+
*/
534+
TargetEntry *ste = get_tle_by_resno(context->sub_tlist,
535+
param->paramid);
536+
537+
if (ste == NULL || ste->resjunk)
538+
elog(ERROR, "subquery output %d not found",
539+
param->paramid);
540+
Assert(param->paramtype == exprType((Node *) ste->expr));
541+
519542
newvar = makeVar(context->rtindex,
520543
param->paramid,
521544
param->paramtype,
522-
-1,
545+
exprTypmod((Node *) ste->expr),
523546
0);
524547

525548
/*
@@ -752,7 +775,8 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
752775
*/
753776
return convert_testexpr(sublink->testexpr,
754777
rtindex,
755-
&ininfo->sub_targetlist);
778+
&ininfo->sub_targetlist,
779+
subselect->targetList);
756780
}
757781

758782
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy