aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/setrefs.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>1999-08-21 03:49:17 +0000
committerTom Lane <tgl@sss.pgh.pa.us>1999-08-21 03:49:17 +0000
commitdb436adf761bd5cb7990745ceba2959ac4bfca7c (patch)
tree8878ce970fd9b3ac480f3c5ef953fbc85827e685 /src/backend/optimizer/plan/setrefs.c
parent5588c559e6e21fae6ba1f162616f4fb4f680fb31 (diff)
downloadpostgresql-db436adf761bd5cb7990745ceba2959ac4bfca7c.tar.gz
postgresql-db436adf761bd5cb7990745ceba2959ac4bfca7c.zip
Major revision of sort-node handling: push knowledge of query
sort order down into planner, instead of handling it only at the very top level of the planner. This fixes many things. An explicit sort is now avoided if there is a cheaper alternative (typically an indexscan) not only for ORDER BY, but also for the internal sort of GROUP BY. It works even when there is no other reason (such as a WHERE condition) to consider the indexscan. It works for indexes on functions. It works for indexes on functions, backwards. It's just so cool... CAUTION: I have changed the representation of SortClause nodes, therefore THIS UPDATE BREAKS STORED RULES. You will need to initdb.
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r--src/backend/optimizer/plan/setrefs.c41
1 files changed, 9 insertions, 32 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 6471ad4e41b..1492df8b030 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.55 1999/08/18 04:15:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.56 1999/08/21 03:49:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -52,7 +52,6 @@ static void replace_vars_with_subplan_refs(Node *clause,
List *subplanTargetList);
static bool replace_vars_with_subplan_refs_walker(Node *node,
replace_vars_with_subplan_refs_context *context);
-static List *pull_agg_clause(Node *clause);
static bool pull_agg_clause_walker(Node *node, List **listptr);
static bool check_having_for_ungrouped_vars_walker(Node *node,
check_having_for_ungrouped_vars_context *context);
@@ -416,23 +415,9 @@ replace_vars_with_subplan_refs_walker(Node *node,
return false;
if (IsA(node, Var))
{
- /*
- * It could be that this varnode has been created by make_groupplan
- * and is already set up to reference the subplan target list. We
- * recognize that case by varno = 1, varnoold = -1, varattno =
- * varoattno, and varlevelsup = 0. (Probably ought to have an
- * explicit flag, but this should do for now.)
- */
Var *var = (Var *) node;
TargetEntry *subplanVar;
- if (var->varno == (Index) 1 &&
- var->varnoold == ((Index) -1) &&
- var->varattno == var->varoattno &&
- var->varlevelsup == 0)
- return false; /* OK to leave it alone */
-
- /* Otherwise it had better be in the subplan list. */
subplanVar = match_varid(var, context->subplanTargetList);
if (!subplanVar)
elog(ERROR, "replace_vars_with_subplan_refs: variable not in target list");
@@ -461,7 +446,6 @@ replace_vars_with_subplan_refs_walker(Node *node,
* the tuples returned by its left tree subplan.
* * If there is a qual list (from a HAVING clause), similarly update
* vars in it to point to the subplan target list.
- * * Generate the aggNode->aggs list of Aggref nodes contained in the Agg.
*
* The return value is TRUE if all qual clauses include Aggrefs, or FALSE
* if any do not (caller may choose to raise an error condition).
@@ -475,7 +459,6 @@ set_agg_tlist_references(Agg *aggNode)
bool all_quals_ok;
subplanTargetList = aggNode->plan.lefttree->targetlist;
- aggNode->aggs = NIL;
foreach(tl, aggNode->plan.targetlist)
{
@@ -484,24 +467,19 @@ set_agg_tlist_references(Agg *aggNode)
replace_vars_with_subplan_refs(tle->expr,
(Index) 0,
subplanTargetList);
- aggNode->aggs = nconc(pull_agg_clause(tle->expr), aggNode->aggs);
}
all_quals_ok = true;
foreach(ql, aggNode->plan.qual)
{
Node *qual = lfirst(ql);
- List *qualaggs;
replace_vars_with_subplan_refs(qual,
(Index) 0,
subplanTargetList);
- qualaggs = pull_agg_clause(qual);
- if (qualaggs == NIL)
+ if (pull_agg_clause(qual) == NIL)
all_quals_ok = false; /* this qual clause has no agg
* functions! */
- else
- aggNode->aggs = nconc(qualaggs, aggNode->aggs);
}
return all_quals_ok;
@@ -514,7 +492,7 @@ set_agg_tlist_references(Agg *aggNode)
* Returns list of Aggref nodes found. Note the nodes themselves are not
* copied, only referenced.
*/
-static List *
+List *
pull_agg_clause(Node *clause)
{
List *result = NIL;
@@ -545,10 +523,6 @@ pull_agg_clause_walker(Node *node, List **listptr)
* exprIsAggOrGroupCol()). But that routine currently does not check subplans,
* because the necessary info is not computed until the planner runs.
* This ought to be cleaned up someday.
- *
- * NOTE: the havingClause has been cnf-ified, so AND subclauses have been
- * turned into a plain List. Thus, this routine has to cope with List nodes
- * where the routine above does not...
*/
void
@@ -588,10 +562,13 @@ check_having_for_ungrouped_vars_walker(Node *node,
foreach(gl, context->groupClause)
{
- Var *groupexpr = get_groupclause_expr(lfirst(gl),
- context->targetList);
+ GroupClause *gcl = lfirst(gl);
+ Node *groupexpr;
- if (var_equal((Var *) thisarg, groupexpr))
+ groupexpr = get_sortgroupclause_expr(gcl,
+ context->targetList);
+ /* XXX is var_equal correct, or should we use equal()? */
+ if (var_equal((Var *) thisarg, (Var *) groupexpr))
{
contained_in_group_clause = true;
break;