Fix more problems with rewriter failing to set Query.hasSubLinks when inserting

a SubLink expression into a rule query.  We missed cases where the original
query contained a sub-SELECT in a function in FROM, a multi-row VALUES list,
or a RETURNING list.  Per bug #4434 from Dean Rasheed and subsequent
investigation.

Back-patch to 8.1; older releases don't have the issue because they didn't
try to be smart about setting hasSubLinks only when needed.
This commit is contained in:
Tom Lane 2008-09-24 16:52:46 +00:00
parent 93eab311e4
commit 96a25d393c

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.179 2008/08/28 23:09:48 tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.180 2008/09/24 16:52:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -346,6 +346,37 @@ rewriteRuleAction(Query *parsetree,
sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
sub_action->rtable);
/*
* There could have been some SubLinks in parsetree's rtable, in which
* case we'd better mark the sub_action correctly.
*/
if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
{
ListCell *lc;
foreach(lc, parsetree->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
switch (rte->rtekind)
{
case RTE_FUNCTION:
sub_action->hasSubLinks =
checkExprHasSubLink(rte->funcexpr);
break;
case RTE_VALUES:
sub_action->hasSubLinks =
checkExprHasSubLink((Node *) rte->values_lists);
break;
default:
/* other RTE types don't contain bare expressions */
break;
}
if (sub_action->hasSubLinks)
break; /* no need to keep scanning rtable */
}
}
/*
* Each rule action's jointree should be the main parsetree's jointree
* plus that rule's jointree, but usually *without* the original rtindex
@ -455,6 +486,14 @@ rewriteRuleAction(Query *parsetree,
rule_action->returningList,
CMD_SELECT,
0);
/*
* There could have been some SubLinks in parsetree's returningList,
* in which case we'd better mark the rule_action correctly.
*/
if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
rule_action->hasSubLinks =
checkExprHasSubLink((Node *) rule_action->returningList);
}
return rule_action;