Skip to content

Commit fb9e56e

Browse files
committed
Suppress subquery pullup/pushdown when a subquery contains volatile
functions in its targetlist, to avoid introducing multiple evaluations of volatile functions that textually appear only once. This is a slightly tighter version of Jaime Casanova's recent patch.
1 parent 9bf760f commit fb9e56e

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

src/backend/optimizer/path/allpaths.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.151 2006/08/10 02:36:28 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.152 2006/08/19 02:48:53 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -871,6 +871,10 @@ compare_tlist_datatypes(List *tlist, List *colTypes,
871871
* 5. We must not push down any quals that refer to subselect outputs that
872872
* return sets, else we'd introduce functions-returning-sets into the
873873
* subquery's WHERE/HAVING quals.
874+
*
875+
* 6. We must not push down any quals that refer to subselect outputs that
876+
* contain volatile functions, for fear of introducing strange results due
877+
* to multiple evaluation of a volatile function.
874878
*/
875879
static bool
876880
qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
@@ -940,6 +944,13 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
940944
safe = false;
941945
break;
942946
}
947+
948+
/* Refuse volatile functions (point 6) */
949+
if (contain_volatile_functions((Node *) tle->expr))
950+
{
951+
safe = false;
952+
break;
953+
}
943954
}
944955

945956
list_free(vars);

src/backend/optimizer/prep/prepjointree.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.42 2006/08/12 20:05:55 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.43 2006/08/19 02:48:53 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -656,6 +656,15 @@ is_simple_subquery(Query *subquery)
656656
if (expression_returns_set((Node *) subquery->targetList))
657657
return false;
658658

659+
/*
660+
* Don't pull up a subquery that has any volatile functions in its
661+
* targetlist. Otherwise we might introduce multiple evaluations of
662+
* these functions, if they get copied to multiple places in the upper
663+
* query, leading to surprising results.
664+
*/
665+
if (contain_volatile_functions((Node *) subquery->targetList))
666+
return false;
667+
659668
/*
660669
* Hack: don't try to pull up a subquery with an empty jointree.
661670
* query_planner() will correctly generate a Result plan for a jointree

0 commit comments

Comments
 (0)