aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/relnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r--src/backend/optimizer/util/relnode.c135
1 files changed, 108 insertions, 27 deletions
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index b4764ab6f8c..86d923116a4 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.32 2001/02/16 00:03:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.33 2001/05/20 20:28:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,7 @@
#include "parser/parsetree.h"
+static RelOptInfo *make_base_rel(Query *root, int relid);
static List *new_join_tlist(List *tlist, int first_resdomno);
static List *build_joinrel_restrictlist(RelOptInfo *joinrel,
RelOptInfo *outer_rel,
@@ -36,28 +37,35 @@ static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,
/*
- * get_base_rel
+ * build_base_rel
* Returns relation entry corresponding to 'relid', creating a new one
* if necessary. This is for base relations.
*/
RelOptInfo *
-get_base_rel(Query *root, int relid)
+build_base_rel(Query *root, int relid)
{
- List *baserels;
+ List *rels;
RelOptInfo *rel;
- foreach(baserels, root->base_rel_list)
+ /* Already made? */
+ foreach(rels, root->base_rel_list)
{
- rel = (RelOptInfo *) lfirst(baserels);
+ rel = (RelOptInfo *) lfirst(rels);
- /*
- * We know length(rel->relids) == 1 for all members of
- * base_rel_list
- */
+ /* length(rel->relids) == 1 for all members of base_rel_list */
if (lfirsti(rel->relids) == relid)
return rel;
}
+ /* It should not exist as an "other" rel */
+ foreach(rels, root->other_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ if (lfirsti(rel->relids) == relid)
+ elog(ERROR, "build_base_rel: rel already exists as 'other' rel");
+ }
+
/* No existing RelOptInfo for this base rel, so make a new one */
rel = make_base_rel(root, relid);
@@ -68,16 +76,52 @@ get_base_rel(Query *root, int relid)
}
/*
+ * build_other_rel
+ * Returns relation entry corresponding to 'relid', creating a new one
+ * if necessary. This is for 'other' relations, which are just like
+ * base relations except that they live in a different list.
+ */
+RelOptInfo *
+build_other_rel(Query *root, int relid)
+{
+ List *rels;
+ RelOptInfo *rel;
+
+ /* Already made? */
+ foreach(rels, root->other_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ /* length(rel->relids) == 1 for all members of other_rel_list */
+ if (lfirsti(rel->relids) == relid)
+ return rel;
+ }
+
+ /* It should not exist as a base rel */
+ foreach(rels, root->base_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ if (lfirsti(rel->relids) == relid)
+ elog(ERROR, "build_other_rel: rel already exists as base rel");
+ }
+
+ /* No existing RelOptInfo for this other rel, so make a new one */
+ rel = make_base_rel(root, relid);
+
+ /* and add it to the list */
+ root->other_rel_list = lcons(rel, root->other_rel_list);
+
+ return rel;
+}
+
+/*
* make_base_rel
* Construct a base-relation RelOptInfo for the specified rangetable index.
*
- * This is split out of get_base_rel so that inheritance-tree processing can
- * construct baserel nodes for child tables. We need a RelOptInfo so we can
- * plan a suitable access path for each child table, but we do NOT want to
- * enter the child nodes into base_rel_list. In most contexts, get_base_rel
- * should be called instead.
+ * Common code for build_base_rel and build_other_rel.
*/
-RelOptInfo *
+static RelOptInfo *
make_base_rel(Query *root, int relid)
{
RelOptInfo *rel = makeNode(RelOptInfo);
@@ -92,7 +136,7 @@ make_base_rel(Query *root, int relid)
rel->cheapest_total_path = NULL;
rel->pruneable = true;
rel->issubquery = false;
- rel->indexed = false;
+ rel->indexlist = NIL;
rel->pages = 0;
rel->tuples = 0;
rel->subplan = NULL;
@@ -108,8 +152,12 @@ make_base_rel(Query *root, int relid)
if (relationObjectId != InvalidOid)
{
/* Plain relation --- retrieve statistics from the system catalogs */
- relation_info(relationObjectId,
- &rel->indexed, &rel->pages, &rel->tuples);
+ bool indexed;
+
+ get_relation_info(relationObjectId,
+ &indexed, &rel->pages, &rel->tuples);
+ if (indexed)
+ rel->indexlist = find_secondary_indexes(relationObjectId);
}
else
{
@@ -121,12 +169,45 @@ make_base_rel(Query *root, int relid)
}
/*
+ * find_base_rel
+ * Find a base or other relation entry, which must already exist
+ * (since we'd have no idea which list to add it to).
+ */
+RelOptInfo *
+find_base_rel(Query *root, int relid)
+{
+ List *rels;
+ RelOptInfo *rel;
+
+ foreach(rels, root->base_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ /* length(rel->relids) == 1 for all members of base_rel_list */
+ if (lfirsti(rel->relids) == relid)
+ return rel;
+ }
+
+ foreach(rels, root->other_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ if (lfirsti(rel->relids) == relid)
+ return rel;
+ }
+
+ elog(ERROR, "find_base_rel: no relation entry for relid %d", relid);
+
+ return NULL; /* keep compiler quiet */
+}
+
+/*
* find_join_rel
* Returns relation entry corresponding to 'relids' (a list of RT indexes),
* or NULL if none exists. This is for join relations.
*
* Note: there is probably no good reason for this to be called from
- * anywhere except get_join_rel, but keep it as a separate routine
+ * anywhere except build_join_rel, but keep it as a separate routine
* just in case.
*/
static RelOptInfo *
@@ -146,7 +227,7 @@ find_join_rel(Query *root, Relids relids)
}
/*
- * get_join_rel
+ * build_join_rel
* Returns relation entry corresponding to the union of two given rels,
* creating a new relation entry if none already exists.
*
@@ -161,11 +242,11 @@ find_join_rel(Query *root, Relids relids)
* duplicated calculation of the restrictlist...
*/
RelOptInfo *
-get_join_rel(Query *root,
- RelOptInfo *outer_rel,
- RelOptInfo *inner_rel,
- JoinType jointype,
- List **restrictlist_ptr)
+build_join_rel(Query *root,
+ RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel,
+ JoinType jointype,
+ List **restrictlist_ptr)
{
List *joinrelids;
RelOptInfo *joinrel;
@@ -212,7 +293,7 @@ get_join_rel(Query *root,
joinrel->cheapest_total_path = NULL;
joinrel->pruneable = true;
joinrel->issubquery = false;
- joinrel->indexed = false;
+ joinrel->indexlist = NIL;
joinrel->pages = 0;
joinrel->tuples = 0;
joinrel->subplan = NULL;