aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c33
-rw-r--r--src/backend/optimizer/plan/planner.c24
-rw-r--r--src/backend/optimizer/prep/prepkeyset.c4
-rw-r--r--src/backend/optimizer/prep/prepunion.c32
-rw-r--r--src/backend/optimizer/util/tlist.c31
5 files changed, 77 insertions, 47 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index ab69742482a..70a73821641 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.81 2000/01/26 05:56:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.82 2000/01/27 18:11:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1342,16 +1342,19 @@ make_group(List *tlist,
}
/*
- * The uniqueAttr argument must be a null-terminated string,
- * either the name of the attribute to select unique on
- * or "*"
+ * distinctList is a list of SortClauses, identifying the targetlist items
+ * that should be considered by the Unique filter.
*/
Unique *
-make_unique(List *tlist, Plan *lefttree, char *uniqueAttr)
+make_unique(List *tlist, Plan *lefttree, List *distinctList)
{
Unique *node = makeNode(Unique);
Plan *plan = &node->plan;
+ int numCols = length(distinctList);
+ int keyno = 0;
+ AttrNumber *uniqColIdx;
+ List *slitem;
copy_plan_costsize(plan, lefttree);
plan->state = (EState *) NULL;
@@ -1361,10 +1364,22 @@ make_unique(List *tlist, Plan *lefttree, char *uniqueAttr)
plan->righttree = NULL;
node->nonameid = _NONAME_RELATION_ID_;
node->keycount = 0;
- if (strcmp(uniqueAttr, "*") == 0)
- node->uniqueAttr = NULL;
- else
- node->uniqueAttr = pstrdup(uniqueAttr);
+
+ /* convert SortClause list into array of attr indexes, as wanted by exec */
+ Assert(numCols > 0);
+ uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
+
+ foreach(slitem, distinctList)
+ {
+ SortClause *sortcl = (SortClause *) lfirst(slitem);
+ TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
+
+ uniqColIdx[keyno++] = tle->resdom->resno;
+ }
+
+ node->numCols = numCols;
+ node->uniqColIdx = uniqColIdx;
+
return node;
}
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 0b711f32099..28483fd4734 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.73 2000/01/26 05:56:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.74 2000/01/27 18:11:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -381,12 +381,12 @@ union_planner(Query *parse)
}
/*
- * Finally, if there is a UNIQUE clause, add the UNIQUE node.
+ * Finally, if there is a DISTINCT clause, add the UNIQUE node.
*/
- if (parse->uniqueFlag)
+ if (parse->distinctClause)
{
result_plan = (Plan *) make_unique(tlist, result_plan,
- parse->uniqueFlag);
+ parse->distinctClause);
}
return result_plan;
@@ -583,20 +583,8 @@ make_sortplan(List *tlist, List *sortcls, Plan *plannode)
foreach(i, sortcls)
{
SortClause *sortcl = (SortClause *) lfirst(i);
- Index refnumber = sortcl->tleSortGroupRef;
- TargetEntry *tle = NULL;
- Resdom *resdom;
- List *l;
-
- foreach(l, temp_tlist)
- {
- tle = (TargetEntry *) lfirst(l);
- if (tle->resdom->ressortgroupref == refnumber)
- break;
- }
- if (l == NIL)
- elog(ERROR, "make_sortplan: ORDER BY expression not found in targetlist");
- resdom = tle->resdom;
+ TargetEntry *tle = get_sortgroupclause_tle(sortcl, temp_tlist);
+ Resdom *resdom = tle->resdom;
/*
* Check for the possibility of duplicate order-by clauses --- the
diff --git a/src/backend/optimizer/prep/prepkeyset.c b/src/backend/optimizer/prep/prepkeyset.c
index 127505597a4..fc192e6f28b 100644
--- a/src/backend/optimizer/prep/prepkeyset.c
+++ b/src/backend/optimizer/prep/prepkeyset.c
@@ -104,9 +104,7 @@ transformKeySetQuery(Query *origNode)
unionNode->isPortal = origNode->isPortal;
unionNode->isBinary = origNode->isBinary;
- if (origNode->uniqueFlag)
- unionNode->uniqueFlag = pstrdup(origNode->uniqueFlag);
-
+ Node_Copy(origNode, unionNode, distinctClause);
Node_Copy(origNode, unionNode, sortClause);
Node_Copy(origNode, unionNode, rtable);
Node_Copy(origNode, unionNode, targetList);
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index a27305ef3e8..4323b652e8d 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.41 2000/01/26 05:56:39 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.42 2000/01/27 18:11:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "optimizer/prep.h"
+#include "optimizer/tlist.h"
#include "parser/parse_clause.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
@@ -131,7 +132,7 @@ plan_union_queries(Query *parse)
!last_union_all_flag)
{
parse->sortClause = NIL;
- parse->uniqueFlag = NULL;
+ parse->distinctClause = NIL;
}
parse->unionClause = NIL; /* prevent recursion */
@@ -183,17 +184,28 @@ plan_union_queries(Query *parse)
if (!last_union_all_flag)
{
/* Need SELECT DISTINCT behavior to implement UNION.
- * Set uniqueFlag properly, put back the held sortClause,
- * and add any missing columns to the sort clause.
+ * Put back the held sortClause, add any missing columns to the
+ * sort clause, and set distinctClause properly.
*/
- parse->uniqueFlag = "*";
+ List *slitem;
+
parse->sortClause = addAllTargetsToSortList(hold_sortClause,
parse->targetList);
+ parse->distinctClause = NIL;
+ foreach(slitem, parse->sortClause)
+ {
+ SortClause *scl = (SortClause *) lfirst(slitem);
+ TargetEntry *tle = get_sortgroupclause_tle(scl, parse->targetList);
+
+ if (! tle->resdom->resjunk)
+ parse->distinctClause = lappend(parse->distinctClause,
+ copyObject(scl));
+ }
}
else
{
- /* needed so we don't take the flag from the first query */
- parse->uniqueFlag = NULL;
+ /* needed so we don't take SELECT DISTINCT from the first query */
+ parse->distinctClause = NIL;
}
/* Make sure we don't try to apply the first query's grouping stuff
@@ -314,9 +326,9 @@ plan_inherit_query(Relids relids,
* Clear the sorting and grouping qualifications in the subquery,
* so that sorting will only be done once after append
*/
- new_root->uniqueFlag = NULL;
- new_root->sortClause = NULL;
- new_root->groupClause = NULL;
+ new_root->distinctClause = NIL;
+ new_root->sortClause = NIL;
+ new_root->groupClause = NIL;
new_root->havingQual = NULL;
new_root->hasAggs = false; /* shouldn't be any left ... */
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 8edf44190a4..b4c745b25f3 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.42 2000/01/26 05:56:40 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.43 2000/01/27 18:11:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -217,15 +217,16 @@ get_expr(TargetEntry *tle)
}
/*
- * get_sortgroupclause_expr
+ * get_sortgroupclause_tle
* Find the targetlist entry matching the given SortClause
- * (or GroupClause) by ressortgroupref, and return its expression.
+ * (or GroupClause) by ressortgroupref, and return it.
*
* Because GroupClause is typedef'd as SortClause, either kind of
* node can be passed without casting.
*/
-Node *
-get_sortgroupclause_expr(SortClause *sortClause, List *targetList)
+TargetEntry *
+get_sortgroupclause_tle(SortClause *sortClause,
+ List *targetList)
{
Index refnumber = sortClause->tleSortGroupRef;
List *l;
@@ -235,9 +236,25 @@ get_sortgroupclause_expr(SortClause *sortClause, List *targetList)
TargetEntry *tle = (TargetEntry *) lfirst(l);
if (tle->resdom->ressortgroupref == refnumber)
- return tle->expr;
+ return tle;
}
- elog(ERROR, "get_sortgroupclause_expr: ORDER/GROUP BY expression not found in targetlist");
+ elog(ERROR, "get_sortgroupclause_tle: ORDER/GROUP BY expression not found in targetlist");
return NULL; /* keep compiler quiet */
}
+
+/*
+ * get_sortgroupclause_expr
+ * Find the targetlist entry matching the given SortClause
+ * (or GroupClause) by ressortgroupref, and return its expression.
+ *
+ * Because GroupClause is typedef'd as SortClause, either kind of
+ * node can be passed without casting.
+ */
+Node *
+get_sortgroupclause_expr(SortClause *sortClause, List *targetList)
+{
+ TargetEntry *tle = get_sortgroupclause_tle(sortClause, targetList);
+
+ return tle->expr;
+}