diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-20 20:28:20 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-20 20:28:20 +0000 |
commit | be03eb25f34c9c95c400504ef76c8abe0081d09f (patch) | |
tree | ca3b081710826485bdaaad375b80e82f5a7fd611 /src/backend/optimizer/util/relnode.c | |
parent | 5d53389cfe5ecacadda12f3a777a642605278e49 (diff) | |
download | postgresql-be03eb25f34c9c95c400504ef76c8abe0081d09f.tar.gz postgresql-be03eb25f34c9c95c400504ef76c8abe0081d09f.zip |
Modify optimizer data structures so that IndexOptInfo lists built for
create_index_paths are not immediately discarded, but are available for
subsequent planner work. This allows avoiding redundant syscache lookups
in several places. Change interface to operator selectivity estimation
procedures to allow faster and more flexible estimation.
Initdb forced due to change of pg_proc entries for selectivity functions!
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 135 |
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; |