Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 63cc56d

Browse files
committed
Suppress subquery pullup and pushdown when the subquery has any
set-returning functions in its target list. This ensures that we won't rewrite the query in a way that places set-returning functions into quals (WHERE clauses). Cf. bug reports from Joe Conway.
1 parent 584f818 commit 63cc56d

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

src/backend/optimizer/path/allpaths.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.82 2001/11/05 17:46:25 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.83 2001/12/10 22:54:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -305,7 +305,14 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
305305
* checking that seems more work than it's worth. In any case, a
306306
* plain DISTINCT is safe to push down past.)
307307
*
308-
* 3. We do not push down clauses that contain subselects, mainly because
308+
* 3. If the subquery has any ITER nodes (ie, functions returning sets)
309+
* in its target list, we do not push down any quals, since the quals
310+
* might refer to those tlist items, which would mean we'd introduce
311+
* functions-returning-sets into the subquery's WHERE/HAVING quals.
312+
* (It'd be sufficient to not push down quals that refer to those
313+
* particular tlist items, but that's much clumsier to check.)
314+
*
315+
* 4. We do not push down clauses that contain subselects, mainly because
309316
* I'm not sure it will work correctly (the subplan hasn't yet
310317
* transformed sublinks to subselects).
311318
*
@@ -318,7 +325,8 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
318325
if (subquery->setOperations == NULL &&
319326
subquery->limitOffset == NULL &&
320327
subquery->limitCount == NULL &&
321-
!has_distinct_on_clause(subquery))
328+
!has_distinct_on_clause(subquery) &&
329+
!contain_iter_clause((Node *) subquery->targetList))
322330
{
323331
/* OK to consider pushing down individual quals */
324332
List *upperrestrictlist = NIL;

src/backend/optimizer/plan/planner.c

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.113 2001/11/05 17:46:26 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.114 2001/12/10 22:54:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -461,6 +461,15 @@ is_simple_subquery(Query *subquery)
461461
subquery->limitCount)
462462
return false;
463463

464+
/*
465+
* Don't pull up a subquery that has any set-returning functions in
466+
* its targetlist. Otherwise we might well wind up inserting
467+
* set-returning functions into places where they mustn't go,
468+
* such as quals of higher queries.
469+
*/
470+
if (contain_iter_clause((Node *) subquery->targetList))
471+
return false;
472+
464473
/*
465474
* Hack: don't try to pull up a subquery with an empty jointree.
466475
* query_planner() will correctly generate a Result plan for a

src/backend/optimizer/util/clauses.c

+35-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.91 2001/11/05 17:46:26 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.92 2001/12/10 22:54:12 tgl Exp $
1212
*
1313
* HISTORY
1414
* AUTHOR DATE MAJOR EVENT
@@ -47,6 +47,7 @@ typedef struct
4747

4848
static bool contain_agg_clause_walker(Node *node, void *context);
4949
static bool pull_agg_clause_walker(Node *node, List **listptr);
50+
static bool contain_iter_clause_walker(Node *node, void *context);
5051
static bool contain_subplans_walker(Node *node, void *context);
5152
static bool pull_subplans_walker(Node *node, List **listptr);
5253
static bool check_subplans_for_ungrouped_vars_walker(Node *node,
@@ -450,6 +451,39 @@ pull_agg_clause_walker(Node *node, List **listptr)
450451
}
451452

452453

454+
/*****************************************************************************
455+
* Iter clause manipulation
456+
*****************************************************************************/
457+
458+
/*
459+
* contain_iter_clause
460+
* Recursively search for Iter nodes within a clause.
461+
*
462+
* Returns true if any Iter found.
463+
*
464+
* XXX Iter is a crock. It'd be better to look directly at each function
465+
* or operator to see if it can return a set. However, that would require
466+
* a lot of extra cycles as things presently stand. The return-type info
467+
* for function and operator nodes should be extended to include whether
468+
* the return is a set.
469+
*/
470+
bool
471+
contain_iter_clause(Node *clause)
472+
{
473+
return contain_iter_clause_walker(clause, NULL);
474+
}
475+
476+
static bool
477+
contain_iter_clause_walker(Node *node, void *context)
478+
{
479+
if (node == NULL)
480+
return false;
481+
if (IsA(node, Iter))
482+
return true; /* abort the tree traversal and return
483+
* true */
484+
return expression_tree_walker(node, contain_iter_clause_walker, context);
485+
}
486+
453487
/*****************************************************************************
454488
* Subplan clause manipulation
455489
*****************************************************************************/

src/include/optimizer/clauses.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: clauses.h,v 1.49 2001/11/05 17:46:34 momjian Exp $
10+
* $Id: clauses.h,v 1.50 2001/12/10 22:54:12 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -42,6 +42,8 @@ extern List *make_ands_implicit(Expr *clause);
4242
extern bool contain_agg_clause(Node *clause);
4343
extern List *pull_agg_clause(Node *clause);
4444

45+
extern bool contain_iter_clause(Node *clause);
46+
4547
extern bool contain_subplans(Node *clause);
4648
extern List *pull_subplans(Node *clause);
4749
extern void check_subplans_for_ungrouped_vars(Query *query);

0 commit comments

Comments
 (0)