aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/costsize.c43
-rw-r--r--src/backend/optimizer/plan/createplan.c238
-rw-r--r--src/backend/optimizer/plan/planner.c31
-rw-r--r--src/backend/optimizer/plan/subselect.c6
-rw-r--r--src/backend/optimizer/util/relnode.c26
5 files changed, 137 insertions, 207 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index b718f8fea18..0f26dc78722 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.61 2000/05/31 00:28:22 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.62 2000/06/18 22:44:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,10 +55,15 @@
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
-#include "optimizer/internal.h"
#include "utils/lsyscache.h"
+/*
+ * The length of a variable-length field in bytes (stupid estimate...)
+ */
+#define _DEFAULT_ATTRIBUTE_WIDTH_ 12
+
+
#define LOG2(x) (log(x) / 0.693147180559945)
#define LOG6(x) (log(x) / 1.79175946922805)
@@ -114,29 +119,17 @@ cost_seqscan(Path *path, RelOptInfo *baserel)
if (!enable_seqscan)
startup_cost += disable_cost;
- /* disk costs */
- if (lfirsti(baserel->relids) < 0)
- {
-
- /*
- * cost of sequentially scanning a materialized temporary relation
- */
- run_cost += _NONAME_SCAN_COST_;
- }
- else
- {
-
- /*
- * The cost of reading a page sequentially is 1.0, by definition.
- * Note that the Unix kernel will typically do some amount of
- * read-ahead optimization, so that this cost is less than the
- * true cost of reading a page from disk. We ignore that issue
- * here, but must take it into account when estimating the cost of
- * non-sequential accesses!
- */
- run_cost += baserel->pages; /* sequential fetches with cost
- * 1.0 */
- }
+ /*
+ * disk costs
+ *
+ * The cost of reading a page sequentially is 1.0, by definition.
+ * Note that the Unix kernel will typically do some amount of
+ * read-ahead optimization, so that this cost is less than the
+ * true cost of reading a page from disk. We ignore that issue
+ * here, but must take it into account when estimating the cost of
+ * non-sequential accesses!
+ */
+ run_cost += baserel->pages; /* sequential fetches with cost 1.0 */
/* CPU costs */
cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost;
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 015b6b2b10a..4915133d0a6 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.92 2000/06/15 03:32:13 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.93 2000/06/18 22:44:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,7 +23,6 @@
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
-#include "optimizer/internal.h"
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
#include "optimizer/restrictinfo.h"
@@ -34,7 +33,6 @@
static List *switch_outer(List *clauses);
-static int set_tlist_sort_info(List *tlist, List *pathkeys);
static Scan *create_scan_node(Query *root, Path *best_path, List *tlist);
static Join *create_join_node(Query *root, JoinPath *best_path, List *tlist);
static SeqScan *create_seqscan_node(Path *best_path, List *tlist,
@@ -71,8 +69,6 @@ static HashJoin *make_hashjoin(List *tlist, List *qpqual,
static Hash *make_hash(List *tlist, Var *hashkey, Plan *lefttree);
static MergeJoin *make_mergejoin(List *tlist, List *qpqual,
List *mergeclauses, Plan *righttree, Plan *lefttree);
-static Material *make_material(List *tlist, Oid nonameid, Plan *lefttree,
- int keycount);
static void copy_path_costsize(Plan *dest, Path *src);
static void copy_plan_costsize(Plan *dest, Plan *src);
static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
@@ -560,10 +556,12 @@ create_nestloop_node(NestPath *best_path,
}
else if (IsA(inner_node, TidScan))
{
- List *inner_tideval = ((TidScan *) inner_node)->tideval;
TidScan *innerscan = (TidScan *) inner_node;
- ((TidScan *) inner_node)->tideval = join_references(inner_tideval, outer_tlist, inner_tlist, innerscan->scan.scanrelid);
+ innerscan->tideval = join_references(innerscan->tideval,
+ outer_tlist,
+ inner_tlist,
+ innerscan->scan.scanrelid);
}
else if (IsA_Join(inner_node))
{
@@ -575,9 +573,8 @@ create_nestloop_node(NestPath *best_path,
* join --- how can we estimate whether this is a good thing to
* do?
*/
- inner_node = (Plan *) make_noname(inner_tlist,
- NIL,
- inner_node);
+ inner_node = (Plan *) make_material(inner_tlist,
+ inner_node);
}
join_node = make_nestloop(tlist,
@@ -632,14 +629,16 @@ create_mergejoin_node(MergePath *best_path,
* necessary. The sort cost was already accounted for in the path.
*/
if (best_path->outersortkeys)
- outer_node = (Plan *) make_noname(outer_tlist,
- best_path->outersortkeys,
- outer_node);
+ outer_node = (Plan *)
+ make_sort_from_pathkeys(outer_tlist,
+ outer_node,
+ best_path->outersortkeys);
if (best_path->innersortkeys)
- inner_node = (Plan *) make_noname(inner_tlist,
- best_path->innersortkeys,
- inner_node);
+ inner_node = (Plan *)
+ make_sort_from_pathkeys(inner_tlist,
+ inner_node,
+ best_path->innersortkeys);
join_node = make_mergejoin(tlist,
qpqual,
@@ -959,72 +958,6 @@ switch_outer(List *clauses)
}
/*
- * set_tlist_sort_info
- * Sets the reskey and reskeyop fields of resdom nodes in a target list
- * for a sort node.
- *
- * 'tlist' is the target list (which is modified in-place).
- * tlist's reskey fields must be clear to start with.
- * 'pathkeys' is the desired pathkeys for the sort. NIL means no sort.
- *
- * Returns the number of sort keys assigned (which might be less than
- * length(pathkeys)!)
- */
-static int
-set_tlist_sort_info(List *tlist, List *pathkeys)
-{
- int keysassigned = 0;
- List *i;
-
- foreach(i, pathkeys)
- {
- List *keysublist = (List *) lfirst(i);
- PathKeyItem *pathkey = NULL;
- Resdom *resdom = NULL;
- List *j;
-
- /*
- * We can sort by any one of the sort key items listed in this
- * sublist. For now, we take the first one that corresponds to an
- * available Var in the tlist.
- *
- * XXX if we have a choice, is there any way of figuring out which
- * might be cheapest to execute? (For example, int4lt is likely
- * much cheaper to execute than numericlt, but both might appear
- * in the same pathkey sublist...) Not clear that we ever will
- * have a choice in practice, so it may not matter.
- */
- foreach(j, keysublist)
- {
- pathkey = lfirst(j);
- Assert(IsA(pathkey, PathKeyItem));
- resdom = tlist_member(pathkey->key, tlist);
- if (resdom)
- break;
- }
- if (!resdom)
- elog(ERROR, "set_tlist_sort_info: cannot find tlist item to sort");
-
- /*
- * The resdom might be already marked as a sort key, if the
- * pathkeys contain duplicate entries. (This can happen in
- * scenarios where multiple mergejoinable clauses mention the same
- * var, for example.) In that case the current pathkey is
- * essentially a no-op, because only one value can be seen within
- * any subgroup where it would be consulted. We can ignore it.
- */
- if (resdom->reskey == 0)
- {
- /* OK, mark it as a sort key and set the sort operator regproc */
- resdom->reskey = ++keysassigned;
- resdom->reskeyop = get_opcode(pathkey->sortop);
- }
- }
-
- return keysassigned;
-}
-
-/*
* Copy cost and size info from a Path node to the Plan node created from it.
* The executor won't use this info, but it's needed by EXPLAIN.
*/
@@ -1078,50 +1011,7 @@ copy_plan_costsize(Plan *dest, Plan *src)
*
*****************************************************************************/
-/*
- * make_noname
- * Create plan node to sort or materialize relations into noname.
- *
- * 'tlist' is the target list of the scan to be sorted or materialized
- * 'pathkeys' is the list of pathkeys by which the result is to be sorted
- * (NIL implies no sort needed, just materialize it)
- * 'subplan' is the node which yields input tuples
- */
-Noname *
-make_noname(List *tlist,
- List *pathkeys,
- Plan *subplan)
-{
- List *noname_tlist;
- int numsortkeys;
- Plan *retval;
-
- /* Create a new target list for the noname, with sort keys set. */
- noname_tlist = new_unsorted_tlist(tlist);
- numsortkeys = set_tlist_sort_info(noname_tlist, pathkeys);
-
- if (numsortkeys > 0)
- {
- /* need to sort */
- retval = (Plan *) make_sort(noname_tlist,
- _NONAME_RELATION_ID_,
- subplan,
- numsortkeys);
- }
- else
- {
- /* no sort */
- retval = (Plan *) make_material(noname_tlist,
- _NONAME_RELATION_ID_,
- subplan,
- 0);
- }
-
- return (Noname *) retval;
-}
-
-
-static SeqScan *
+static SeqScan *
make_seqscan(List *qptlist,
List *qpqual,
Index scanrelid)
@@ -1256,8 +1146,14 @@ make_mergejoin(List *tlist,
return node;
}
+/*
+ * To use make_sort directly, you must already have marked the tlist
+ * with reskey and reskeyop information. The keys had better be
+ * non-redundant, too (ie, there had better be tlist items marked with
+ * each key number from 1 to keycount), or the executor will get confused!
+ */
Sort *
-make_sort(List *tlist, Oid nonameid, Plan *lefttree, int keycount)
+make_sort(List *tlist, Plan *lefttree, int keycount)
{
Sort *node = makeNode(Sort);
Plan *plan = &node->plan;
@@ -1272,17 +1168,84 @@ make_sort(List *tlist, Oid nonameid, Plan *lefttree, int keycount)
plan->qual = NIL;
plan->lefttree = lefttree;
plan->righttree = NULL;
- node->nonameid = nonameid;
node->keycount = keycount;
return node;
}
-static Material *
-make_material(List *tlist,
- Oid nonameid,
- Plan *lefttree,
- int keycount)
+/*
+ * make_sort_from_pathkeys
+ * Create sort plan to sort according to given pathkeys
+ *
+ * 'tlist' is the target list of the input plan
+ * 'lefttree' is the node which yields input tuples
+ * 'pathkeys' is the list of pathkeys by which the result is to be sorted
+ *
+ * We must convert the pathkey information into reskey and reskeyop fields
+ * of resdom nodes in the sort plan's target list.
+ */
+Sort *
+make_sort_from_pathkeys(List *tlist, Plan *lefttree, List *pathkeys)
+{
+ List *sort_tlist;
+ List *i;
+ int numsortkeys = 0;
+
+ /* Create a new target list for the sort, with sort keys set. */
+ sort_tlist = new_unsorted_tlist(tlist);
+
+ foreach(i, pathkeys)
+ {
+ List *keysublist = (List *) lfirst(i);
+ PathKeyItem *pathkey = NULL;
+ Resdom *resdom = NULL;
+ List *j;
+
+ /*
+ * We can sort by any one of the sort key items listed in this
+ * sublist. For now, we take the first one that corresponds to an
+ * available Var in the sort_tlist.
+ *
+ * XXX if we have a choice, is there any way of figuring out which
+ * might be cheapest to execute? (For example, int4lt is likely
+ * much cheaper to execute than numericlt, but both might appear
+ * in the same pathkey sublist...) Not clear that we ever will
+ * have a choice in practice, so it may not matter.
+ */
+ foreach(j, keysublist)
+ {
+ pathkey = lfirst(j);
+ Assert(IsA(pathkey, PathKeyItem));
+ resdom = tlist_member(pathkey->key, sort_tlist);
+ if (resdom)
+ break;
+ }
+ if (!resdom)
+ elog(ERROR, "make_sort_from_pathkeys: cannot find tlist item to sort");
+
+ /*
+ * The resdom might be already marked as a sort key, if the
+ * pathkeys contain duplicate entries. (This can happen in
+ * scenarios where multiple mergejoinable clauses mention the same
+ * var, for example.) In that case the current pathkey is
+ * essentially a no-op, because only one value can be seen within
+ * any subgroup where it would be consulted. We can ignore it.
+ */
+ if (resdom->reskey == 0)
+ {
+ /* OK, mark it as a sort key and set the sort operator regproc */
+ resdom->reskey = ++numsortkeys;
+ resdom->reskeyop = get_opcode(pathkey->sortop);
+ }
+ }
+
+ Assert(numsortkeys > 0);
+
+ return make_sort(sort_tlist, lefttree, numsortkeys);
+}
+
+Material *
+make_material(List *tlist, Plan *lefttree)
{
Material *node = makeNode(Material);
Plan *plan = &node->plan;
@@ -1291,8 +1254,9 @@ make_material(List *tlist,
/*
* For plausibility, make startup & total costs equal total cost of
- * input plan; this only affects EXPLAIN display not decisions. XXX
- * shouldn't we charge some additional cost for materialization?
+ * input plan; this only affects EXPLAIN display not decisions.
+ *
+ * XXX shouldn't we charge some additional cost for materialization?
*/
plan->startup_cost = plan->total_cost;
plan->state = (EState *) NULL;
@@ -1300,8 +1264,6 @@ make_material(List *tlist,
plan->qual = NIL;
plan->lefttree = lefttree;
plan->righttree = NULL;
- node->nonameid = nonameid;
- node->keycount = keycount;
return node;
}
@@ -1420,8 +1382,6 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList)
plan->qual = NIL;
plan->lefttree = lefttree;
plan->righttree = NULL;
- node->nonameid = _NONAME_RELATION_ID_;
- node->keycount = 0;
/*
* convert SortClause list into array of attr indexes, as wanted by
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index fdb7be92447..49d400dee9d 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.83 2000/06/15 03:32:13 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.84 2000/06/18 22:44:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,7 +21,6 @@
#include "executor/executor.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
-#include "optimizer/internal.h"
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
@@ -40,7 +39,7 @@ static List *make_subplanTargetList(Query *parse, List *tlist,
static Plan *make_groupplan(List *group_tlist, bool tuplePerGroup,
List *groupClause, AttrNumber *grpColIdx,
bool is_presorted, Plan *subplan);
-static Plan *make_sortplan(List *tlist, List *sortcls, Plan *plannode);
+static Plan *make_sortplan(List *tlist, Plan *plannode, List *sortcls);
/*****************************************************************************
*
@@ -641,7 +640,8 @@ union_planner(Query *parse,
if (parse->sortClause)
{
if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys))
- result_plan = make_sortplan(tlist, parse->sortClause, result_plan);
+ result_plan = make_sortplan(tlist, result_plan,
+ parse->sortClause);
}
/*
@@ -818,10 +818,9 @@ make_groupplan(List *group_tlist,
}
}
- subplan = (Plan *) make_sort(sort_tlist,
- _NONAME_RELATION_ID_,
- subplan,
- keyno);
+ Assert(keyno > 0);
+
+ subplan = (Plan *) make_sort(sort_tlist, subplan, keyno);
}
return (Plan *) make_group(group_tlist, tuplePerGroup, numCols,
@@ -833,9 +832,9 @@ make_groupplan(List *group_tlist,
* Add a Sort node to implement an explicit ORDER BY clause.
*/
static Plan *
-make_sortplan(List *tlist, List *sortcls, Plan *plannode)
+make_sortplan(List *tlist, Plan *plannode, List *sortcls)
{
- List *temp_tlist;
+ List *sort_tlist;
List *i;
int keyno = 0;
@@ -843,13 +842,12 @@ make_sortplan(List *tlist, List *sortcls, Plan *plannode)
* First make a copy of the tlist so that we don't corrupt the
* original.
*/
-
- temp_tlist = new_unsorted_tlist(tlist);
+ sort_tlist = new_unsorted_tlist(tlist);
foreach(i, sortcls)
{
SortClause *sortcl = (SortClause *) lfirst(i);
- TargetEntry *tle = get_sortgroupclause_tle(sortcl, temp_tlist);
+ TargetEntry *tle = get_sortgroupclause_tle(sortcl, sort_tlist);
Resdom *resdom = tle->resdom;
/*
@@ -865,10 +863,9 @@ make_sortplan(List *tlist, List *sortcls, Plan *plannode)
}
}
- return (Plan *) make_sort(temp_tlist,
- _NONAME_RELATION_ID_,
- plannode,
- keyno);
+ Assert(keyno > 0);
+
+ return (Plan *) make_sort(sort_tlist, plannode, keyno);
}
/*
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 87e508ef8f7..cd624fb111d 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.37 2000/05/30 00:49:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.38 2000/06/18 22:44:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -363,9 +363,7 @@ make_subplan(SubLink *slink)
}
if (use_material)
{
- plan = (Plan *) make_noname(plan->targetlist,
- NIL,
- plan);
+ plan = (Plan *) make_material(plan->targetlist, plan);
node->plan = plan;
}
}
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index da7059ce915..070fabf7669 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -8,14 +8,13 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.26 2000/04/12 17:15:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.27 2000/06/18 22:44:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "optimizer/cost.h"
-#include "optimizer/internal.h"
#include "optimizer/joininfo.h"
#include "optimizer/pathnode.h"
#include "optimizer/plancat.h"
@@ -76,26 +75,9 @@ get_base_rel(Query *root, int relid)
rel->joininfo = NIL;
rel->innerjoin = NIL;
- if (relid < 0)
- {
-
- /*
- * If the relation is a materialized relation, assume constants
- * for sizes.
- */
- rel->pages = _NONAME_RELATION_PAGES_;
- rel->tuples = _NONAME_RELATION_TUPLES_;
- }
- else
- {
-
- /*
- * Otherwise, retrieve relation statistics from the system
- * catalogs.
- */
- relation_info(root, relid,
- &rel->indexed, &rel->pages, &rel->tuples);
- }
+ /* Retrieve relation statistics from the system catalogs. */
+ relation_info(root, relid,
+ &rel->indexed, &rel->pages, &rel->tuples);
root->base_rel_list = lcons(rel, root->base_rel_list);