88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.97 2004/01/0505:07:35 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.98 2004/01/0518:04:39 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2020#include "executor/executor.h"
2121#include "miscadmin.h"
2222#include "nodes/plannodes.h"
23+ #include "optimizer/clauses.h"
2324#include "optimizer/cost.h"
2425#include "optimizer/pathnode.h"
2526#include "optimizer/paths.h"
2627#include "optimizer/restrictinfo.h"
2728#include "parser/parse_expr.h"
2829#include "parser/parse_oper.h"
30+ #include "parser/parsetree.h"
2931#include "utils/memutils.h"
3032#include "utils/selfuncs.h"
3133#include "utils/syscache.h"
@@ -546,6 +548,30 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
546548
547549pathnode -> subpath = subpath ;
548550
551+ /*
552+ * If the input is a subquery that uses DISTINCT, we don't need to do
553+ * anything; its output is already unique. (Are there any other cases
554+ * in which we can easily prove the input must be distinct?)
555+ */
556+ if (rel -> rtekind == RTE_SUBQUERY )
557+ {
558+ RangeTblEntry * rte = rt_fetch (rel -> relid ,root -> rtable );
559+ Query * subquery = rte -> subquery ;
560+
561+ if (has_distinct_clause (subquery ))
562+ {
563+ pathnode -> umethod = UNIQUE_PATH_NOOP ;
564+ pathnode -> rows = rel -> rows ;
565+ pathnode -> path .startup_cost = subpath -> startup_cost ;
566+ pathnode -> path .total_cost = subpath -> total_cost ;
567+ pathnode -> path .pathkeys = subpath -> pathkeys ;
568+
569+ rel -> cheapest_unique_path = (Path * )pathnode ;
570+
571+ return pathnode ;
572+ }
573+ }
574+
549575/*
550576 * Try to identify the targetlist that will actually be unique-ified.
551577 * In current usage, this routine is only used for sub-selects of IN
@@ -599,7 +625,7 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
599625 * compare costs. We only try this if we know the targetlist for sure
600626 * (else we can't be sure about the datatypes involved).
601627 */
602- pathnode -> use_hash = false ;
628+ pathnode -> umethod = UNIQUE_PATH_SORT ;
603629if (enable_hashagg && sub_targetlist && hash_safe_tlist (sub_targetlist ))
604630{
605631/*
@@ -617,11 +643,11 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
617643subpath -> total_cost ,
618644rel -> rows );
619645if (agg_path .total_cost < sort_path .total_cost )
620- pathnode -> use_hash = true ;
646+ pathnode -> umethod = UNIQUE_PATH_HASH ;
621647}
622648}
623649
624- if (pathnode -> use_hash )
650+ if (pathnode -> umethod == UNIQUE_PATH_HASH )
625651{
626652pathnode -> path .startup_cost = agg_path .startup_cost ;
627653pathnode -> path .total_cost = agg_path .total_cost ;