Skip to content

Commit eeb3abe

Browse files
committed
Ignore resjunk targetlist entries when matching arguments to
a SubLink with the subplan's targetlist. This fixes a problem seen with, for example, a subselect that uses GROUP BY.
1 parent 8c32f99 commit eeb3abe

File tree

1 file changed

+33
-22
lines changed

1 file changed

+33
-22
lines changed

src/backend/parser/parse_expr.c

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.49 1999/05/26 12:55:37 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.50 1999/07/11 02:04:19 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -278,7 +278,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
278278
SubLink *sublink = (SubLink *) expr;
279279
List *qtrees;
280280
Query *qtree;
281-
List *llist;
282281

283282
pstate->p_hasSubLinks = true;
284283
qtrees = parse_analyze(lcons(sublink->subselect, NIL), pstate);
@@ -293,36 +292,48 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
293292
if (sublink->subLinkType != EXISTS_SUBLINK)
294293
{
295294
char *op = lfirst(sublink->oper);
296-
List *left_expr = sublink->lefthand;
297-
List *right_expr = ((Query *) sublink->subselect)->targetList;
295+
List *left_list = sublink->lefthand;
296+
List *right_list = qtree->targetList;
298297
List *elist;
299298

300-
foreach(llist, left_expr)
301-
lfirst(llist) = transformExpr(pstate, lfirst(llist), precedence);
299+
foreach(elist, left_list)
300+
lfirst(elist) = transformExpr(pstate, lfirst(elist),
301+
precedence);
302302

303-
if (length(left_expr) != length(right_expr))
304-
elog(ERROR, "parser: Subselect has too many or too few fields.");
305-
306-
if (length(left_expr) > 1 &&
303+
if (length(left_list) > 1 &&
307304
strcmp(op, "=") != 0 && strcmp(op, "<>") != 0)
308-
elog(ERROR, "parser: '%s' is not relational operator", op);
305+
elog(ERROR, "parser: '%s' is not relational operator",
306+
op);
309307

310308
sublink->oper = NIL;
311-
foreach(elist, left_expr)
309+
310+
/* Scan subquery's targetlist to find values that will be
311+
* matched against lefthand values. We need to ignore
312+
* resjunk targets, so doing the outer iteration over
313+
* right_list is easier than doing it over left_list.
314+
*/
315+
while (right_list != NIL)
312316
{
313-
Node *lexpr = lfirst(elist);
314-
Node *rexpr = lfirst(right_expr);
315-
TargetEntry *tent = (TargetEntry *) rexpr;
317+
TargetEntry *tent = (TargetEntry *) lfirst(right_list);
318+
Node *lexpr;
316319
Expr *op_expr;
317320

318-
op_expr = make_op(op, lexpr, tent->expr);
319-
320-
if (op_expr->typeOid != BOOLOID &&
321-
sublink->subLinkType != EXPR_SUBLINK)
322-
elog(ERROR, "parser: '%s' must return 'bool' to be used with quantified predicate subquery", op);
323-
sublink->oper = lappend(sublink->oper, op_expr);
324-
right_expr = lnext(right_expr);
321+
if (! tent->resdom->resjunk)
322+
{
323+
if (left_list == NIL)
324+
elog(ERROR, "parser: Subselect has too many fields.");
325+
lexpr = lfirst(left_list);
326+
left_list = lnext(left_list);
327+
op_expr = make_op(op, lexpr, tent->expr);
328+
if (op_expr->typeOid != BOOLOID &&
329+
sublink->subLinkType != EXPR_SUBLINK)
330+
elog(ERROR, "parser: '%s' must return 'bool' to be used with quantified predicate subquery", op);
331+
sublink->oper = lappend(sublink->oper, op_expr);
332+
}
333+
right_list = lnext(right_list);
325334
}
335+
if (left_list != NIL)
336+
elog(ERROR, "parser: Subselect has too few fields.");
326337
}
327338
else
328339
sublink->oper = NIL;

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