Recognize that IN subqueries return already-unique results if they use
UNION/INTERSECT/EXCEPT (without ALL). This adds on to the previous optimization for subqueries using DISTINCT.
This commit is contained in:
parent
5c625a9326
commit
864412fd0a
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.99 2004/01/05 23:39:54 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.100 2004/01/19 03:49:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -33,6 +33,7 @@
|
|||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
|
static bool is_distinct_query(Query *query);
|
||||||
static bool hash_safe_tlist(List *tlist);
|
static bool hash_safe_tlist(List *tlist);
|
||||||
|
|
||||||
|
|
||||||
@ -553,16 +554,14 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
|
|||||||
pathnode->subpath = subpath;
|
pathnode->subpath = subpath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the input is a subquery that uses DISTINCT, we don't need to do
|
* If the input is a subquery whose output must be unique already,
|
||||||
* anything; its output is already unique. (Are there any other cases
|
* we don't need to do anything.
|
||||||
* in which we can easily prove the input must be distinct?)
|
|
||||||
*/
|
*/
|
||||||
if (rel->rtekind == RTE_SUBQUERY)
|
if (rel->rtekind == RTE_SUBQUERY)
|
||||||
{
|
{
|
||||||
RangeTblEntry *rte = rt_fetch(rel->relid, root->rtable);
|
RangeTblEntry *rte = rt_fetch(rel->relid, root->rtable);
|
||||||
Query *subquery = rte->subquery;
|
|
||||||
|
|
||||||
if (has_distinct_clause(subquery))
|
if (is_distinct_query(rte->subquery))
|
||||||
{
|
{
|
||||||
pathnode->umethod = UNIQUE_PATH_NOOP;
|
pathnode->umethod = UNIQUE_PATH_NOOP;
|
||||||
pathnode->rows = rel->rows;
|
pathnode->rows = rel->rows;
|
||||||
@ -667,6 +666,36 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
|
|||||||
return pathnode;
|
return pathnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is_distinct_query - does query never return duplicate rows?
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
is_distinct_query(Query *query)
|
||||||
|
{
|
||||||
|
/* DISTINCT (but not DISTINCT ON) guarantees uniqueness */
|
||||||
|
if (has_distinct_clause(query))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* UNION, INTERSECT, EXCEPT guarantee uniqueness, except with ALL */
|
||||||
|
if (query->setOperations)
|
||||||
|
{
|
||||||
|
SetOperationStmt *topop = (SetOperationStmt *) query->setOperations;
|
||||||
|
|
||||||
|
Assert(IsA(topop, SetOperationStmt));
|
||||||
|
Assert(topop->op != SETOP_NONE);
|
||||||
|
|
||||||
|
if (!topop->all)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Are there any other cases in which we can easily see the result
|
||||||
|
* must be distinct?
|
||||||
|
*/
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hash_safe_tlist - can datatypes of given tlist be hashed?
|
* hash_safe_tlist - can datatypes of given tlist be hashed?
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user